Überprüfen der Objektintegrität in Amazon S3 - Amazon Simple Storage Service

Überprüfen der Objektintegrität in Amazon S3

Amazon S3 verwendet Prüfsummenwerte, um die Datenintegrität beim Hoch- und Herunterladen zu überprüfen. Wenn Sie Daten hochladen, verwenden das AWS SDK und die AWS-Managementkonsole den von Ihnen gewählten Prüfsummenalgorithmus, um vor der Datenübertragung einen Prüfsummenwert zu berechnen. S3 berechnet dann selbständig eine Prüfsumme über Ihre Daten und vergleicht sie mit dem angegebenen Prüfsummenwert. Die Objekte werden nur angenommen, wenn bestätigt wurde, dass die Datenintegrität während der Übertragung gewahrt wurde. S3 speichert sowohl den Prüfsummenwert als Objekt-Metadaten als auch das Objekt selbst.

Um die Integrität von Objekten zu überprüfen, können Sie beim Herunterladen den Prüfsummenwert abfragen. Diese Validierung funktioniert konsistent über alle Verschlüsselungsmodi, Objektgrößen, Speicherklassen und sowohl ein- als auch mehrteilige Uploads. Um den Prüfsummenalgorithmus für einen Upload zu ändern, können Sie ein einzelnes Objekt kopieren oder die Stapelkopie für mehrere Objekte verwenden.

Bei Uploads einzelner Teile können Sie Prüfsummenwerte als Header angeben. Sie können entweder einen vorberechneten Wert angeben oder das AWS SDK während des Hochladens einen Wert berechnen lassen. Wenn der von S3 berechnete Prüfsummenwert mit dem von Ihnen angegebenen Wert übereinstimmt, wird die Anfrage akzeptiert. Wenn die Werte nicht übereinstimmen, wird die Anfrage abgelehnt.

Bei mehrteiligen Uploads können AWS SDKs automatisch abschließende Prüfsummen für Chunked Uploads erstellen. Wenn Sie eine abschließende Prüfsumme verwenden, generiert Amazon S3 Prüfsummenwerte für jeden Teil mit dem von Ihnen angegebenen Algorithmus und hängt den Prüfsummenwert an das Ende der Chunked-Upload-Anforderung an. S3 führt die Überprüfung und den Upload in einem einzigen Durchgang durch, was die Effizienz erhöht. Weitere Informationen hierzu finden Sie unter Verwenden von nachfolgenden Prüfsummen.

Verwenden unterstützter Prüfsummenalgorithmen

Bei Amazon S3 können Sie einen Prüfsummenalgorithmus wählen, um die Prüfsummenwerte beim Hochladen zu berechnen. Der angegebene Prüfsummenalgorithmus wird dann zusammen mit Ihrem Objekt gespeichert und kann zur Überprüfung der Datenintegrität bei Downloads verwendet werden. Sie können einen der folgenden Secure Hash Algorithms (SHA)- oder Cyclic Redundancy Check (CRC)-Prüfsummenalgorithmen auswählen, um den Prüfsummenwert zu berechnen:

  • CRC-64/NVME (CRC64NVME)

  • CRC-32 (CRC32)

  • CRC-32C (CRC32C)

  • SHA-1 (SHA1)

  • SHA-256 (SHA256)

  • MD5 (MD5)

    Anmerkung

    Der content-MD5-Header ist nur unter Verwendung des S3 ETag für Objekte verfügbar, die in einem Einzelteil-Upload (PUT-Operation) hochgeladen werden, der die SSE-S3-Verschlüsselung verwendet.

Darüber hinaus können Sie mit dem Content-MD5-Header für jede Anforderung eine Prüfsumme angeben.

Wenn Sie ein Objekt hochladen, können Sie den Algorithmus angeben, den Sie verwenden möchten:

  • Wenn Sie die AWS-Managementkonsole verwenden, wählen Sie den Prüfsummenalgorithmus aus, den Sie verwenden möchten. Sie können den Prüfsummenwert des Objekts optional angeben. Wenn Amazon S3 das Objekt erhält, berechnet es die Prüfsumme mithilfe des von Ihnen angegebenen Algorithmus. Wenn die beiden Prüfsummenwerte nicht übereinstimmen, generiert Amazon S3 einen Fehler.

  • Wenn Sie ein SDK verwenden, beachten Sie Folgendes:

    • Legen Sie den ChecksumAlgorithm-Parameter auf den Algorithmus fest, den Amazon S3 verwenden soll. Wenn Sie bereits über eine vorberechnete Prüfsumme verfügen, übergeben Sie den Prüfsummenwert an das AWS-SDK und das SDK nimmt den Wert in die Anforderung auf. Wenn Sie keinen Prüfsummenwert übergeben oder keinen Prüfsummenalgorithmus angeben, berechnet das SDK automatisch einen Prüfsummenwert für Sie und fügt ihn zum Integritätsschutz in die Anforderung ein. Wenn der individuelle Prüfsummenwert nicht mit dem festgelegten Wert des Prüfsummenalgorithmus übereinstimmt, schlägt die Anforderung in Amazon S3 mit einem BadDigest-Fehler fehl.

    • Wenn Sie ein aktualisiertes AWS-SDK verwenden, wählt das SDK einen Prüfsummenalgorithmus für Sie aus. Sie können jedoch diesen Prüfsummenalgorithmus außer Kraft setzen.

    • Wenn Sie keinen Prüfsummenalgorithmus angeben und das SDK auch keine Prüfsumme für Sie berechnet, dann wählt S3 automatisch den CRC-64/NVME (CRC64NVME) Prüfsummenalgorithmus.

  • Bei Verwendung der REST-API nutzen Sie den x-amz-sdk-checksum-algorithm-Parameter nicht. Verwenden Sie stattdessen einen der algorithmenspezifischen Header (z. B. x-amz-checksum-crc32).

Um einen dieser Prüfsummenwerte auf Objekte anzuwenden, die bereits in Amazon S3 hochgeladen wurden, können Sie das Objekt kopieren und angeben, ob Sie den bestehenden Prüfsummenalgorithmus oder einen neuen verwenden möchten. Wenn Sie keinen Algorithmus angeben, verwendet S3 den vorhandenen Algorithmus. Wenn für das Quellobjekt kein Prüfsummenalgorithmus oder Prüfsummenwert angegeben ist, verwendet Amazon S3 den CRC-64/NVME-Algorithmus, um den Prüfsummenwert für das Zielobjekt zu berechnen. Sie können auch einen Prüfsummenalgorithmus angeben, wenn Sie Objekte mit S3 Batch Operations kopieren.

Wichtig

Wenn Sie einen mehrteiligen Upload mit Prüfsummen für zusammengesetzte Prüfsummen (oder Prüfsummen auf Teilebene) verwenden, müssen die Teilnummern des mehrteiligen Uploads fortlaufend sein und mit 1 beginnen. Wenn Sie versuchen, eine mehrteilige Upload-Anforderung mit nicht aufeinanderfolgenden Teilenummern abzuschließen, generiert Amazon S3 einen HTTP 500 Internal Server-Fehler.

Vollständige Objekt- und zusammengesetzte Prüfsummentypen

In Amazon S3 gibt es zwei Arten von unterstützten Prüfsummen:

  • Vollständige Objektprüfsummen: Eine vollständige Objektprüfsumme wird auf der Grundlage des gesamten Inhalts eines mehrteiligen Uploads berechnet und deckt alle Daten vom ersten Byte des ersten Teils bis zum letzten Byte des letzten Teils ab. Beachten Sie, dass beim Hochladen von Objekten, die kleiner als 16 MB sind, mit AWS-Managementkonsole nur der vollständige Objektprüfsummentyp unterstützt wird.

    Anmerkung

    Alle PUT-Anforderungen erfordern einen vollständigen Objektprüfsummentyp. Sie müssen einen vollständigen Objektprüfsummentyp angeben, wenn Sie Ihr Objekt per PUT-Anforderung hochladen.

  • Zusammengesetzte Prüfsummen: Eine zusammengesetzte Prüfsumme wird auf der Grundlage der einzelnen Prüfsummen jedes Teils in einem mehrteiligen Upload berechnet. Anstatt eine Prüfsumme auf der Grundlage des gesamten Dateninhalts zu berechnen, aggregiert dieser Ansatz die Prüfsummen auf Teilebene (vom ersten bis zum letzten Teil), um eine einzige, kombinierte Prüfsumme für das gesamte Objekt zu erhalten. Wenn Sie einen mehrteiligen Upload verwenden, um Ihr Objekt hochzuladen, müssen Sie den Typ der zusammengesetzten Prüfsumme angeben.

    Anmerkung

    Wenn ein Objekt als mehrteiliger Upload hochgeladen wird, ist das ETag für das Objekt kein MD5-Digest des gesamten Objekts. Amazon S3 berechnet stattdessen den MD5-Digest jedes einzelnen Teils beim Hochladen. Die MD5-Digests werden verwendet, um das ETag für das endgültige Objekt zu bestimmen. Amazon S3 verkettet die Bytes für die MD5-Digests und berechnet dann den MD5-Digest dieser verketteten Werte. Während des letzten Schritts der Erstellung des ETag fügt Amazon S3 einen Bindestrich mit der Gesamtanzahl der Teile am Ende hinzu.

Amazon S3 unterstützt die folgenden Typen von vollständigen Objekt- und zusammengesetzten Prüfsummenalgorithmen:

  • CRC-64/NVME (CRC64NVME): Unterstützt nur den vollständigen Objekt-Prüfsummus.

  • CRC-32 (CRC32): Unterstützt sowohl vollständige Objekt- als auch zusammengesetzte Prüfsummustypen.

  • CRC-32C (CRC32C): Unterstützt sowohl vollständige Objekt- als auch zusammengesetzte Prüfsummustypen.

  • SHA-1 (SHA1): Unterstützt sowohl vollständige Objekt- als auch zusammengesetzte Prüfsummustypen.

  • SHA-256 (SHA256): Unterstützt sowohl vollständige Objekt- als auch zusammengesetzte Prüfsummustypen.

  • MD5 (MD5): Unterstützt sowohl vollständige Objekt- als auch zusammengesetzte Algorithmustypen.

Uploads einzelner Teile

Prüfsummen von Objekten, die in einem einzigen Teil (mit PutObject) hochgeladen werden, werden als vollständige Objektprüfsummen behandelt. Wenn Sie ein Objekt in die Amazon-S3-Konsole hochladen, können Sie den Prüfsummenalgorithmus auswählen, den S3 verwenden soll, und (optional) auch einen vorberechneten Wert angeben. Amazon S3 validiert dann den vorberechneten Prüfsummenwert, bevor das Objekt und sein Prüfsummenwert gespeichert werden. Sie können die Datenintegrität eines Objekts überprüfen, wenn Sie den Prüfsummenwert beim Herunterladen von Objekten anfordern.

Mehrteilige Uploads

Wenn Sie das Objekt mithilfe der MultipartUpload-API in mehreren Teilen hochladen, können Sie den Prüfsummenalgorithmus, den Amazon S3 verwenden soll, und den Prüfsummentyp (vollständiges Objekt oder zusammengesetzt) angeben.

Die folgende Tabelle zeigt, welcher Prüfsummenalgorithmus für jeden Prüfsummenalgorithmus in einem mehrteiligen Upload unterstützt wird:

Prüfsummenalgorithmus Vollständiges Objekt Zusammengesetzt
CRC-64/NVME (CRC64NVME) Ja Nein
CRC-32 (CRC32) Ja Ja
CRC-32C (CRC32C) Ja Ja
SHA-1 (SHA1) Nein Ja
SHA-256 (SHA256) Nein Ja

Verwenden vollständiger Objektprüfsummen für den mehrteiligen Upload

Wenn Sie einen mehrteiligen Upload erstellen oder durchführen, können Sie vollständige Objektprüfsummen für die Validierung beim Upload verwenden. Das bedeutet, dass Sie den Prüfsummenalgorithmus für die MultipartUpload-API bereitstellen können, was Ihre Tools zur Integritätsprüfung vereinfacht, da Sie die Teilgrenzen für hochgeladene Objekte nicht mehr verfolgen müssen. Sie können die Prüfsumme des gesamten Objekts in der CompleteMultipartUpload-Anforderung zusammen mit der Objektgröße angeben.

Wenn Sie während eines mehrteiligen Uploads eine vollständige Objektprüfsumme angeben, übergibt das AWS-SDK die Prüfsumme an Amazon S3 und S3 validiert die Objektintegrität serverseitig und vergleicht sie mit dem empfangenen Wert. Anschließend speichert Amazon S3 das Objekt, wenn die Werte übereinstimmen. Wenn die beiden Werte nicht übereinstimmen, schlägt S3 mit einem BadDigest-Fehler fehl. Die Prüfsumme Ihres Objekts wird auch in den Objektmetadaten gespeichert, die Sie später zur Validierung der Datenintegrität des Objekts verwenden.

Für vollständige Objektprüfsummen können Sie in S3 die Prüfsummenalgorithmen CRC-64/NVME (CRC64NVME), CRC-32 (CRC32) oder CRC-32C (CRC32C) verwenden. Vollständige Objektprüfsummen in mehrteiligen Uploads sind nur für CRC-basierte Prüfsummen verfügbar, da sie zu einer vollständigen Objektprüfsumme linearisiert werden können. Diese Linearisierung ermöglicht es Amazon S3, Ihre Anfragen zu parallelisieren, um die Leistung zu verbessern. Insbesondere kann S3 die Prüfsumme des gesamten Objekts aus den Prüfsummen auf Teilebene berechnen. Diese Art der Validierung ist für andere Algorithmen wie SHA und MD5 nicht verfügbar. Da S3 über einen standardmäßigen Integritätsschutz verfügt, fügt S3 beim Hochladen von Objekten ohne Prüfsumme automatisch den empfohlenen vollständigen Objekt-CRC-64/NVME (CRC64NVME) Prüfsummenalgorithmus an das Objekt an.

Anmerkung

Um den mehrteiligen Upload zu initiieren, können Sie den Prüfsummenalgorithmus und den vollständigen Objektprüfsummentyp angeben. Nachdem Sie den Prüfsummenalgorithmus und den Prüfsummentyp für das vollständige Objekt angegeben haben, können Sie den vollständigen Objektprüfsummenwert für den mehrteiligen Upload angeben.

Verwenden von Prüfsummen auf Teilebene für mehrteilige Uploads

Wenn Objekte zu Amazon S3 hochgeladen werden, können sie entweder als einzelnes Objekt oder mithilfe des mehrteiligen Upload-Prozesses in Teilen hochgeladen werden. Sie können einen Prüfsummentyp für Ihren mehrteiligen Upload wählen. Für mehrteilige Uploads mit Prüfsummen auf Teilebene (oder zusammengesetzte Prüfsummen) berechnet Amazon S3 die Prüfsumme für jeden einzelnen Teil mithilfe des angegebenen Prüfsummenalgorithmus. Sie können UploadPart verwenden, um die Prüfsummenwerte für jeden Teil anzugeben. Wenn das Objekt, das Sie in der Amazon-S3-Konsole hochzuladen versuchen, auf die Verwendung des CRC-64/NVME (CRC64NVME)-Prüfsummenalgorithmus eingestellt ist und mehr als 16 MB umfasst, wird es automatisch als vollständige Objektprüfsumme bezeichnet.

Amazon S3 verwendet dann die gespeicherten Prüfsummenwerte auf Teilebene, um zu bestätigen, dass jeder Teil korrekt hochgeladen wurde. Wenn die Prüfsumme jedes Teils (für das gesamte Objekt) angegeben wird, verwendet S3 die gespeicherten Prüfsummenwerte der einzelnen Teile, um intern die vollständige Objektprüfsumme zu berechnen und sie mit dem angegebenen Prüfsummenwert zu vergleichen. Dadurch werden die Rechenkosten minimiert, da S3 anhand der Prüfsumme der Teile eine Prüfsumme des gesamten Objekts berechnen kann. Weitere Informationen über mehrteilige Uploads finden Sie unter Hochladen und Kopieren von Objekten mit mehrteiligen Uploads in Amazon S3 und Verwenden vollständiger Objektprüfsummen für den mehrteiligen Upload.

Wenn das Objekt vollständig hochgeladen ist, können Sie die endgültige berechnete Prüfsumme verwenden, um die Datenintegrität des Objekts zu überprüfen.

Beachten Sie Folgendes beim Hochladen eines Teils des mehrteiligen Uploads:

  • Um Informationen über das Objekt abzurufen, einschließlich der Anzahl der Teile, aus denen das gesamte Objekt besteht, können Sie die GetObjectAttributes-Operation verwenden. Mit zusätzlichen Prüfsummen können Sie auch Informationen für jeden einzelnen Teil wiederherstellen, der den Prüfsummenwert jedes Teils enthält.

  • Alternativ können Sie die Prüfsumme eines einzelnen Teils abrufen, indem Sie die GetObject- oder HeadObject-Operation verwenden und eine Teilenummer oder einen Bytebereich angeben, der an einem einzelnen Teil ausgerichtet ist. Wenn Sie die Prüfsummenwerte für einzelne Teile von mehrteiligen Uploads abrufen möchten, die noch in Bearbeitung sind, können Sie verwenden ListParts.

  • Aufgrund der Art und Weise, wie Amazon S3 die Prüfsumme für mehrteilige Objekte berechnet, kann sich der Prüfsummenwert für das Objekt ändern, wenn Sie es kopieren. Wenn Sie ein SDK oder die REST-API verwenden und CopyObject aufrufen, kopiert Amazon S3 jedes Objekt bis zu den Größenbeschränkungen der CopyObject-API-Operation. Amazon S3 führt diese Kopie als einzelne Aktion aus, unabhängig davon, ob das Objekt in einer einzigen Anforderung oder im Rahmen eines mehrteiligen Uploads hochgeladen wurde. Mit einem Kopierbefehl ist die Prüfsumme des Objekts eine direkte Prüfsumme des vollständigen Objekts. Wenn das Objekt ursprünglich mithilfe eines mehrteiligen Uploads hochgeladen wurde, ändert sich der Prüfsummenwert, obwohl die Daten unverändert bleiben.

  • Objekte, die die Größenbeschränkungen der CopyObject-API-Operation überschreiten, müssen mehrteilige Upload-Kopierbefehle verwenden.

  • Wenn Sie einige Operationen mit der AWS-Managementkonsole durchführen, verwendet Amazon S3 einen mehrteiligen Upload, wenn das Objekt größer als 16 MB ist.

Prüfsummenmethode

Nach dem Hochladen von Objekten können Sie den Prüfsummenwert abrufen und ihn mit einem vorberechneten oder zuvor gespeicherten Prüfsummenwert desselben Prüfsummenalgorithmus vergleichen. Die folgenden Beispiele zeigen Ihnen, welche Prüfsummenberechnungsmethoden Sie zur Überprüfung der Datenintegrität verwenden können.

Weitere Informationen zur Verwendung der Konsole und zum Angeben von Prüfsummenalgorithmen, die beim Hochladen von Objekten verwendet werden, finden Sie unter Objekte hochladen und unter Tutorial: Überprüfen der Integrität von Daten in Amazon S3 mit zusätzlichen Prüfsummen.

Das folgende Beispiel zeigt, wie Sie die AWS-SDKs verwenden, um eine große Datei mit mehrteiligem Upload hochzuladen, eine große Datei herunterzuladen und eine mehrteilige Upload-Datei zu validieren, wobei jeweils SHA-256 für die Dateivalidierung verwendet wird.

Java
Beispiel: Hochladen, Herunterladen und Verifizieren einer großen Datei mit SHA-256

Anweisungen zum Erstellen und Testen eines funktionierenden Beispiels finden Sie unter Erste Schritte im AWS SDK für Java-Entwicklerhandbuch.

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

Sie können REST-Anforderungen senden, um ein Objekt mit einem Prüfsummenwert hochzuladen und die Integrität der Daten mit PutObject zu verifizieren. Sie können den Prüfsummenwert für Objekte auch mit GetObject oder HeadObject abrufen.

Sie können eine PUT-Anforderung zum Hochladen eines Objekts von bis zu 5 GB in einem einzigen Vorgang senden. Weitere Informationen finden Sie unter PutObject in der AWS CLI-Befehlszeilenreferenz. Sie können auch get-object und head-object verwenden, um die Prüfsumme eines bereits hochgeladenen Objekts abzurufen und die Integrität der Daten zu überprüfen.

Weitere Informationen finden Sie unter Häufig gestellte Fragen zur Amazon-S3-CLI im AWS Command Line Interface-Benutzerhandbuch.

Verwenden von Content-MD5 beim Hochladen von Objekten

Eine andere Möglichkeit, die Integrität Ihres Objekts nach dem Hochladen zu überprüfen, besteht darin, beim Hochladen einen MD5-Digest des Objekts bereitzustellen. Wenn Sie den MD5-Digest für Ihr Objekt berechnen, können Sie den Digest mit dem PUT-Befehl unter Verwendung des Content-MD5-Headers angeben.

Nach dem Hochladen des Objekts berechnet Amazon S3 den MD5-Digest des Objekts und vergleicht ihn mit dem von Ihnen angegebenen Wert. Die Anforderung ist nur erfolgreich, wenn die beiden Digests übereinstimmen.

Die Bereitstellung eines MD5-Digest ist nicht erforderlich, aber Sie können damit die Integrität des Objekts im Rahmen des Upload-Prozesses überprüfen.

Verwenden von Content-MD5 und des ETag, um hochgeladene Objekte zu überprüfen

Das Entity-Tag (ETag) für ein Objekt stellt eine bestimmte Version dieses Objekts dar. Hinweis: Das ETag berücksichtigt nur Änderungen am Inhalt eines Objekts, nicht an seinen Metadaten. Wenn sich nur die Metadaten eines Objekts ändern, bleibt das ETag gleich.

Je nach Objekt kann das ETag des Objekts ein MD5-Digest der Objektdaten sein:

  • Wenn ein Objekt über die Operation PutObject, PostObject oder CopyObject oder über die AWS-Managementkonsole erstellt wird und dieses Objekt außerdem Klartext oder durch serverseitige Verschlüsselung mit von Amazon S3 verwalteten Schlüsseln (SSE-S3) verschlüsselt ist, verfügt dieses Objekt über ein ETag, das ein MD5-Digest seiner Objektdaten ist.

  • Wenn ein Objekt von der PutObject-, PostObject- oder der CopyObject-Operation oder von der AWS-Managementkonsole erstellt wird und dieses Objekt durch serverseitige Verschlüsselung mit vom Kunden bereitgestellten Schlüsseln (SSE-C) oder durch serverseitige Verschlüsselung mit AWS Key Management Service (AWS KMS)-Schlüsseln (SSE-KMS) verschlüsselt ist, verfügt das Objekt über ein ETag, das kein MD5-Digest seiner Objektdaten ist.

  • Wenn ein Objekt entweder durch den mehrteiligen Upload-Prozess oder die UploadPartCopy-Operation erstellt wird, ist der ETag des Objekts kein MD5-Digest, unabhängig von der verwendeten Verschlüsselungsmethode. Wenn ein Objekt größer als 16 MB ist, kopiert oder lädt die AWS-Managementkonsole dieses Objekt als mehrteiligen Upload hoch. Daher handelt es sich beim ETag nicht um ein MD5-Digest.

Für Objekte, bei denen das ETag dem Content-MD5-Digest des Objekts entspricht, können Sie den ETag-Wert des Objekts mit einem berechneten oder zuvor gespeicherten Content-MD5-Digest vergleichen.

Verwenden von nachfolgenden Prüfsummen

Wenn Sie große Objekte in Amazon S3 hochladen, können Sie entweder eine vorberechnete Prüfsumme für das Objekt bereitstellen oder ein AWS SDK verwenden, um in Ihrem Namen automatisch abschließende Prüfsummen für Chunked-Uploads zu erstellen. Wenn Sie eine abschließende Prüfsumme verwenden, generiert Amazon S3 beim Hochladen eines Objekts automatisch den Prüfsummenwert unter Verwendung des von Ihnen angegebenen Algorithmus, um die Integrität des Objekts in Chunked Uploads zu überprüfen.

Wenn Sie eine nachfolgende Prüfsumme bei Verwendung eines AWS-SDK erstellen möchten, tragen Sie Ihren bevorzugten Algorithmus in den ChecksumAlgorithm-Parameter ein. Das SDK verwendet diesen Algorithmus, um den Prüfsummenwert für Ihr Objekt (oder Objektteile) zu berechnen, und fügt ihn automatisch an das Ende Ihrer Chunked-Upload-Anforderung an. Dank dieser Funktionsweise sparen Sie Zeit, da Amazon S3 sowohl die Überprüfung als auch das Hochladen Ihrer Daten in einem einzigen Durchgang durchführt.

Wichtig

Wenn Sie S3 Object Lambda verwenden, werden alle Anfragen an S3 Object Lambda mit s3-object-lambda anstelle von s3 signiert. Dieses Verhalten wirkt sich auf die Signatur der nachfolgenden Prüfsummenwerte aus. Weitere Informationen zu S3 Object Lambda finden Sie unter Transformieren von Objekten mit S3 Object Lambda.

Nachfolgende Prüfsummen-Header

Für die Anforderung einer Chunked-Content-Codierung verlangt Amazon S3 von den Client-Servern, dass sie mehrere Header enthalten, um die Anforderung korrekt zu analysieren. Client-Server müssen die folgenden Header enthalten:

  • x-amz-decoded-content-length:Dieser Header gibt die Klartextgröße der tatsächlichen Daten an, die mit der Anforderung in Amazon S3 hochgeladen werden.

  • x-amz-content-sha256: Dieser Header gibt den Typ des Chunked Uploads an, der in der Anfrage enthalten ist. Bei Chunked Uploads mit abschließenden Prüfsummen lautet der Header-Wert STREAMING-UNSIGNED-PAYLOAD-TRAILER für Anfragen, die keine Nutzdatensignierung verwenden, und STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER für Anfragen, die SigV4-Nutzdatensignierung verwenden. (Weitere Informationen zur Implementierung signierter Nutzdaten finden Sie unter Signaturberechnungen für den Autorization Header: Übertragen von Nutzdaten in mehreren Chunks.)

  • x-amz-trailer: Diese Kopfzeile gibt den Namen der abschließenden Kopfzeile in der Anfrage an. Wenn nachgestellte Prüfsummen vorhanden sind (wenn AWS SDKs Prüfsummen an die verschlüsselten Anforderungskörper anhängen), enthält der x-amz-trailer -Header-Wert das Präfix x-amz-checksum- und endet mit dem Algorithmusnamen. Folgende x-amz-trailer-Werte werden derzeit unterstützt:

    • x-amz-checksum-crc32

    • x-amz-checksum-crc32c

    • x-amz-checksum-crc64nvme

    • x-amz-checksum-sha1

    • x-amz-checksum-sha256

Anmerkung

Sie können auch den Content-Encoding-Header mit dem Chunked-Wert in Ihre Anfrage aufnehmen. Dieser Header ist zwar nicht erforderlich, kann aber bei der Übertragung von verschlüsselten Daten Probleme mit dem HTTP-Proxy minimieren. Wenn in der Anfrage ein anderer Content-Encoding Header (z. B. gzip) vorhanden ist, enthält der Content-Encoding Header den aufgeteilten Wert in einer durch Kommas getrennten Liste von Kodierungen. Beispiel, Content-Encoding: aws-chunked, gzip.

Gehackte Teile

Wenn Sie ein Objekt mit Chunked Encoding in Amazon S3 hochladen, enthält die Upload-Anforderung die folgenden Arten von Chunks (in der aufgeführten Reihenfolge formatiert):

  • Object body chunks: Einer Chunked-Upload-Anforderung können ein, mehrere oder keine Body Chunks zugeordnet sein.

  • Komplettierungs-Chunks: Mit einer Chunked-Upload-Anforderung können ein, mehrere oder keine Body Chunks verbunden sein.

  • Abschließende Chunks: Die abschließende Prüfsumme wird nach dem Abschluss-Chunk aufgeführt. Es ist nur ein Chunk am Ende erlaubt.

Anmerkung

Jeder Chunked-Upload muss mit einem abschließenden CRLF (z. B. \r\n) enden, um das Ende der Anforderung anzuzeigen.

Beispiele für die Chunked-Formatierung finden Sie unter Beispiele: Chunked Uploads mit nachgestellten Prüfsummen.

Objektkörper-Brocken

Object Body Chunks sind die Chunks, die die eigentlichen Objektdaten enthalten, die in S3 hochgeladen werden. Diese Chunks haben einheitliche Größen- und Formatbeschränkungen.

Objektkörper-Stückgröße

Diese Chunks müssen mindestens 8.192 Byte (oder 8 KiB) an Objektdaten enthalten, mit Ausnahme des Final Body Chunks, der kleiner sein kann. Es gibt keine explizite maximale Chunk-Größe, aber Sie können davon ausgehen, dass alle Chunks kleiner als die maximale Upload-Größe von 5 GB sind. Die Größe der Chunks kann je nach Client-Server-Implementierung von einem Chunk zum nächsten variieren.

Objektkörper-Chunk-Format

Objektkörperchunks beginnen mit der hexadezimalen Kodierung der Anzahl der Bytes im Objektkörperchunk, gefolgt von einem CRLF (Carriage Return Line Feed), den Objektbytes für diesen Chunk und einem weiteren CRLF.

Zum Beispiel:

hex-encoding-of-object-bytes-in-chunk\r\n chunk-object-bytes\r\n

Wenn der Chunk jedoch signiert ist, folgt der Objektkörper-Chunk einem anderen Format, bei dem die Signatur an die Chunk-Größe mit einem Semikolon als Trennzeichen angehängt wird. Zum Beispiel:

hex-encoding-of-object-bytes-in-chunk;chunk-signature\r\n chunk-object-bytes\r\n

Für weitere Informationen über Chunk-Signierung siehe Signaturberechnungen für den Authorization Header: Übertragen von Nutzdaten in mehreren Chunks (AWS Signatur Version 4). Weitere Informationen zur Chunk-Formatierung finden Sie unter Chunked transfer encoding auf der RFC Editor Website.

Vervollständigung von Chunks

Completion Chunks müssen das letzte Object Body Chunk jedes Chunked Uploads sein. Ein Completion Chunk hat ein ähnliches Format wie ein Body Chunk, enthält aber immer null Bytes an Objektdaten. (Die Null-Bytes der Objektdaten zeigen an, dass alle Daten hochgeladen worden sind). Chunked Uploads müssen einen Completion Chunk als abschließenden Object Body Chunk enthalten, und zwar in folgendem Format:

0\r\n

Wenn die Anforderung zur Inhaltskodierung jedoch eine Nutzdatensignierung verwendet, wird stattdessen dieses Format verwendet:

0;chunk-signature\r\n

Trailer-Brocken

Trailer Chunks enthalten die berechnete Prüfsumme für alle S3-Upload-Anfragen. Trailer Chunks enthalten zwei Felder: ein Header-Namensfeld und ein Header-Wertfeld. Das Feld für den Namen der Kopfzeile einer Upload-Anforderung muss mit dem Wert übereinstimmen, der in der Kopfzeile der Anforderung x-amz-trailer angegeben ist. Wenn eine Anfrage beispielsweise x-amz-trailer: x-amz-checksum-crc32 enthält und der Trailer-Chunk den Header-Namen x-amz-checksum-sha1hat, schlägt die Anfrage fehl. Das Feld value im trailer chunk enthält eine base64-Kodierung des Big-Endian-Prüfsummenwertes für dieses Objekt. (Die Big-Endian-Reihenfolge speichert das höchstwertige Byte der Daten an der niedrigsten Speicheradresse und das niedrigstwertige Byte an der größten Speicheradresse). Der zur Berechnung dieser Prüfsumme verwendete Algorithmus ist derselbe wie das Suffix für den Namen der Kopfzeile (z. B. crc32).

Format des Anhängerstücks

Trailer Chunks verwenden das folgende Format für unsignierte Nutzdatenanforderungen:

x-amz-checksum-lowercase-checksum-algorithm-name:base64-checksum-value\n\r\n\r\n

Bei Anfragen mit SigV4-signierten Nutzdatenenthält der Trailer-Chunk eine Trailer-Signatur nach dem Trailer-Chunk.

trailer-checksum\n\r\n trailer-signature\r\n

Sie können das CRLF auch direkt an das Ende des base64-Prüfsummenwerts anhängen. Zum Beispiel:

x-amz-checksum-lowercase-checksum-algorithm-name:base64-checksum-value\r\n\r\n

Beispiele: Chunked Uploads mit nachgestellten Prüfsummen

Amazon S3 unterstützt Chunked Uploads, die aws-chunked Inhaltskodierung für PutObject und UploadPart Anfragen mit abschließenden Prüfsummen verwenden.

Beispiel 1 – Unsignierte blockierte PutObject-Anforderung mit einer abschließenden CRC-32-Prüfsumme

Nachfolgend sehen Sie ein Beispiel für eine PutObject Chunk-Anfrage mit einer abschließenden CRC-32-Prüfsumme. In diesem Beispiel lädt der Client ein 17-KB-Objekt in drei unsignierten Chunks hoch und fügt einen abschließenden CRC-32-Prüfsummen-Chunk mit Hilfe des x-amz-checksum-crc32-Headers an.

PUT /Key+ HTTP/1.1 Host: amzn-s3-demo-bucket Content-Encoding: aws-chunked x-amz-decoded-content-length: 17408 x-amz-content-sha256: STREAMING-UNSIGNED-PAYLOAD-TRAILER x-amz-trailer: x-amz-checksum-crc32 2000\r\n // Object body chunk 1 (8192 bytes) object-bytes\r\n 2000\r\n // Object body chunk 2 (8192 bytes) object-bytes\r\n 400\r\n // Object body chunk 3 (1024 bytes) object-bytes\r\n 0\r\n // Completion chunk x-amz-checksum-crc32:YABb/g==\n\r\n\r\n // Trailer chunk (note optional \n character) \r\n // CRLF

Hier ist ein Beispiel für eine Antwort:

HTTP/1.1 200 ETag: ETag x-amz-checksum-crc32: YABb/g==
Anmerkung

Die Verwendung des Zeilenvorschubs \n am Ende des Prüfsummenwerts kann von Client zu Client unterschiedlich sein.

Beispiel 2 – SigV4-signierte PutObject-Chunk-Anforderung mit abschließender CRC-32-(CRC32)-Prüfsumme

Nachfolgend sehen Sie ein Beispiel für eine PutObject Chunk-Anfrage mit einer abschließenden CRC-32-Prüfsumme. Diese Anfrage verwendet die SigV4-Nutzdatensignierung. In diesem Beispiel lädt der Kunde ein 17 KB großes Objekt in drei signierten Chunks hoch. Neben den Chunks object body sind auch die Chunks completion chunk und trailer chunk signiert.

PUT /Key+ HTTP/1.1 Host: amzn-s3-demo-bucket.s3.amazonaws.com Content-Encoding: aws-chunked x-amz-decoded-content-length: 17408 x-amz-content-sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER x-amz-trailer: x-amz-checksum-crc32 authorization-code // SigV4 headers authorization 2000;chunk-signature=signature-value...\r\n // Object body chunk 1 (8192 bytes) object-bytes\r\n 2000;chunk-signature\r\n // Object body chunk 2 (8192 bytes) object-bytes\r\n 400;chunk-signature\r\n // Object body chunk 3 (1024 bytes) object-bytes\r\n 0;chunk-signature\r\n // Completion chunk x-amz-checksum-crc32:YABb/g==\n\r\n // Trailer chunk (note optional \n character) trailer-signature\r\n \r\n // CRLF

Hier ist ein Beispiel für eine Antwort:

HTTP/1.1 200 ETag: ETag x-amz-checksum-crc32: YABb/g==