Sélectionner vos préférences de cookies

Nous utilisons des cookies essentiels et des outils similaires qui sont nécessaires au fonctionnement de notre site et à la fourniture de nos services. Nous utilisons des cookies de performance pour collecter des statistiques anonymes afin de comprendre comment les clients utilisent notre site et d’apporter des améliorations. Les cookies essentiels ne peuvent pas être désactivés, mais vous pouvez cliquer sur « Personnaliser » ou « Refuser » pour refuser les cookies de performance.

Si vous êtes d’accord, AWS et les tiers approuvés utiliseront également des cookies pour fournir des fonctionnalités utiles au site, mémoriser vos préférences et afficher du contenu pertinent, y compris des publicités pertinentes. Pour accepter ou refuser tous les cookies non essentiels, cliquez sur « Accepter » ou « Refuser ». Pour effectuer des choix plus détaillés, cliquez sur « Personnaliser ».

Vérification de l’intégrité des objets dans Amazon S3

Mode de mise au point
Vérification de l’intégrité des objets dans Amazon S3 - Amazon Simple Storage Service

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Amazon S3 utilise des valeurs de somme de contrôle pour vérifier l’intégrité des données que vous chargez ou téléchargez. En outre, vous pouvez demander qu’un autre total de contrôle soit calculé pour tout objet que vous stockez dans Amazon S3. Vous pouvez choisir un algorithme de somme de contrôle à utiliser lors du chargement, de la copie standard ou de la copie par lot de vos données.

Lorsque vous chargez vos données, Amazon S3 utilise l’algorithme que vous avez choisi pour calculer une somme de contrôle côté serveur et la valide avec la valeur fournie avant de stocker l’objet et de stocker la somme de contrôle dans le cadre des métadonnées de l’objet. Cette validation fonctionne de manière cohérente quels que soient les modes de chiffrement, les tailles d’objets et les classes de stockage pour les chargements en une seule partie ou les chargements partitionnés. Cependant, lorsque vous copiez vos données de manière standard ou par lot, Amazon S3 calcule la somme de contrôle de l’objet source et la transfère vers l’objet de destination.

Note

Lorsque vous effectuez un chargement en une seule partie ou un chargement partitionné, vous pouvez intégrer une somme de contrôle précalculée à votre demande et utiliser le type de somme de contrôle de l’objet entier. Pour utiliser des valeurs précalculées avec plusieurs objets, utilisez le ou. AWS CLI AWS SDKs

Utilisation des algorithmes de total de contrôle pris en charge

Avec Amazon S3, vous pouvez choisir un algorithme de somme de contrôle pour valider vos données lors des chargements. L’algorithme de somme de contrôle spécifié est ensuite stocké avec l’objet et peut être utilisé pour valider l’intégrité des données lors des chargements. Vous pouvez sélectionner l’un des algorithmes suivants de somme de contrôle Secure Hash Algorithms (SHA) ou Cyclic Redundancy Check (CRC) pour calculer la valeur de la somme de contrôle :

  • CRC-64/NVME () CRC64NVME

  • CRC-32 () CRC32

  • CRC-32C () CRC32C

  • SHA-1 () SHA1

  • SHA-256 () SHA256

En outre, vous pouvez fournir une somme de contrôle pour chaque demande à l'aide de l'MD5en-tête Content-.

Lorsque vous chargez un objet, vous spécifiez l’algorithme que vous souhaitez utiliser :

  • Lorsque vous utilisez le AWS Management Console, choisissez l'algorithme de somme de contrôle que vous souhaitez utiliser. Vous avez la possibilité de spécifier la valeur de la somme de contrôle de l’objet. Lorsque Amazon S3 reçoit l’objet, il calcule le total de contrôle en utilisant l’algorithme que vous avez spécifié. Si les deux valeurs ne correspondent pas, Amazon S3 génère une erreur.

  • Lorsque vous utilisez un kit SDK, gardez à l’esprit les points suivants :

    • Définissez le paramètre ChecksumAlgorithm selon l’algorithme que vous souhaitez qu’Amazon S3 utilise. Si vous disposez déjà d'une somme de contrôle précalculée, vous transmettez la valeur de la somme de contrôle au AWS SDK, qui inclut la valeur dans la demande. Si vous ne transmettez pas de valeur de somme de contrôle ou ne spécifiez pas d’algorithme de somme de contrôle, le kit SDK calculera automatiquement une valeur de somme de contrôle pour vous et l’inclura dans la demande afin de fournir des protections d’intégrité. Si la valeur de somme de contrôle individuelle ne correspond pas à la valeur définie par l’algorithme de somme de contrôle, Amazon S3 abandonne la demande avec une erreur BadDigest.

    • Si vous utilisez un AWS SDK mis à jour, celui-ci choisit un algorithme de somme de contrôle pour vous. Vous pouvez toutefois remplacer cet algorithme.

    • Si vous ne spécifiez pas d'algorithme de somme de contrôle et que le SDK ne calcule pas non plus de somme de contrôle pour vous, S3 choisit automatiquement l'algorithme de somme de contrôle CRC-64/NVME (). CRC64NVME

  • Lorsque vous utilisez l’API REST, n’utilisez pas le paramètre x-amz-sdk-checksum-algorithm. Utilisez plutôt l’un des en-têtes spécifiques à l’algorithme (par exemple, x-amz-checksum-crc32).

Pour appliquer ces valeurs de somme de contrôle à des objets déjà chargés sur Amazon S3, vous pouvez copier l’objet et spécifier si vous voulez utiliser l’algorithme de somme de contrôle existant ou un autre. Si vous ne spécifiez aucun algorithme, S3 utilise l’algorithme existant. Si l'objet source ne possède pas d'algorithme de somme de contrôle ou de valeur de somme de contrôle spécifié, Amazon S3 utilise l'algorithme CRC-64/NVME pour calculer la valeur de somme de contrôle pour l'objet de destination. Vous pouvez spécifier un algorithme de somme de contrôle lors de la copie d’objets à l’aide des opérations par lot S3.

Important

Si vous utilisez un chargement partitionné avec des sommes de contrôle pour des sommes de contrôle composites (ou au niveau des parties), les numéros de pièce du téléchargement partitionné doivent être consécutifs et commencer par 1. Si vous essayez de finaliser une demande de chargement partitionné avec des numéros de partie non consécutifs, Amazon S3 génère une erreur HTTP 500 Internal Server.

Types de sommes de contrôle d’objet entier et composites

Dans Amazon S3, deux types de sommes de contrôle sont pris en charge :

  • Sommes de contrôle des objets entiers : la somme de contrôle d’un objet entier est calculée sur la base de l’ensemble du contenu d’un chargement partitionné, couvrant toutes les données allant du premier octet de la première partie chargée au dernier octet de la dernière partie chargée.

    Note

    Toutes les demandes PUT nécessitent un type de somme de contrôle d’objet entier.

  • Sommes de contrôle composites : une somme de contrôle composite est calculée sur la base des sommes de contrôle individuelles de chaque partie d’un chargement partitionné. Au lieu de calculer une somme de contrôle basée sur l’ensemble du contenu des données, cette approche agrège les sommes de contrôle au niveau de chaque partie (de la première à la dernière) afin de générer une somme de contrôle unique combinée pour l’objet entier.

    Note

    Lorsqu'un objet est chargé en plusieurs parties, la balise d'entité (ETag) de l'objet n'est pas un MD5 condensé de l'objet dans son intégralité. Amazon S3 calcule plutôt le MD5 résumé de chaque partie individuelle au fur et à mesure de son chargement. Les MD5 résumés sont utilisés pour déterminer l' ETag objet final. Amazon S3 concatène les octets des MD5 résumés, puis calcule le MD5 condensé de ces valeurs concaténées. Au cours de la dernière étape de ETag création, Amazon S3 ajoute un tiret indiquant le nombre total de pièces jusqu'à la fin.

Amazon S3 prend en charge les types de sommes de contrôle d’objet entier et les types de sommes de contrôle composites suivants :

  • CRC-64/NVME (CRC64NVME) : Supporte uniquement le type d'algorithme d'objet complet.

  • CRC-32 (CRC32) : Supporte à la fois les types d'objets complets et les types d'algorithmes composites.

  • CRC-32C (CRC32C) : Supporte à la fois les types d'objets complets et les types d'algorithmes composites.

  • SHA-1 (SHA1) : Supporte à la fois les types d'objets complets et les types d'algorithmes composites.

  • SHA-256 (SHA256) : Supporte à la fois les types d'objets complets et les types d'algorithmes composites.

Chargements en une seule partie

Les sommes de contrôle des objets chargés en une seule partie (à l’aide de PutObject) sont traitées comme des sommes de contrôle d’objets entiers. Lorsque vous chargez un objet dans la console Amazon S3, vous pouvez choisir l’algorithme de somme de contrôle que vous souhaitez que S3 utilise et, si vous le souhaitez, vous pouvez aussi fournir une valeur précalculée. Amazon S3 valide ensuite cette somme de contrôle avant de stocker l’objet et sa valeur de somme contrôle. Vous pouvez vérifier l’intégrité des données d’un objet lorsque vous demandez la valeur de la somme de contrôle lors du chargement de l’objet.

Chargements partitionnés

Lorsque vous chargez l’objet en plusieurs parties à l’aide de l’API MultipartUpload, vous pouvez spécifier l’algorithme de somme de contrôle que vous souhaitez qu’Amazon S3 utilise et le type de somme de contrôle (objet entier ou composite).

Le tableau suivant indique quel type d’algorithme de somme de contrôle est pris en charge pour chaque algorithme de somme de contrôle d’un chargement partitionné :

Algorithme de somme de contrôle Objet complet Composite
CRC-64/NVME () CRC64NVME Oui Non
CRC-32 () CRC32 Oui Oui
CRC-32C () CRC32C Oui Oui
SHA-1 () SHA1 Oui Oui
SHA-256 () SHA256 Oui Oui

Utilisation des sommes de contrôle des objets entiers pour le chargement partitionné

Lorsque vous créez ou effectuez un chargement partitionné, vous pouvez utiliser les sommes de contrôle de l’objet entier pour la validation du chargement. Cela signifie que vous pouvez fournir l’algorithme de somme de contrôle pour l’API MultipartUpload, ce qui simplifie les outils de validation de l’intégrité, car vous n’avez plus besoin de suivre les limites de chaque partie pour les objets chargés. Vous pouvez fournir la somme de contrôle de l’objet entier dans la demande CompleteMultipartUpload, ainsi que la taille de l’objet.

Lorsque vous fournissez une somme de contrôle complète d'un objet lors d'un chargement en plusieurs parties, le AWS SDK transmet la somme de contrôle à Amazon S3, et S3 valide l'intégrité de l'objet côté serveur, en la comparant à la valeur reçue. Amazon S3 stocke ensuite l’objet si les valeurs correspondent. Si les deux valeurs ne correspondent pas, S3 fait échouer la demande et génère une erreur BadDigest. La somme de contrôle de votre objet est également stockée dans les métadonnées de l’objet que vous utiliserez ultérieurement pour valider l’intégrité des données d’un objet.

Pour les sommes de contrôle complètes des objets, vous pouvez utiliser les algorithmes de somme de contrôle CRC-64/NVME (CRC64NVME), CRC-32 (CRC32) ou CRC-32C () dans S3. CRC32C Les sommes de contrôle des objets entiers dans les chargements partitionnés ne sont disponibles que pour les sommes de contrôle basées sur l’algorithme CRC, car elles peuvent être linéarisées en une somme de contrôle pour l’objet entier. Cette linéarisation permet à Amazon S3 de paralléliser vos demandes pour améliorer les performances. S3 peut notamment calculer la somme de contrôle de l’objet entier à partir des sommes de contrôle au niveau de chaque partie. Ce type de validation n'est pas disponible pour les autres algorithmes, tels que SHA et MD5. Comme S3 dispose de protections d'intégrité par défaut, si des objets sont chargés sans somme de contrôle, S3 attache automatiquement l'algorithme de somme de contrôle CRC-64/NVME (CRC64NVME) recommandé pour l'ensemble de l'objet à l'objet.

Note

Pour lancer le chargement partitionné, vous pouvez spécifier l’algorithme de somme de contrôle et le type de somme de contrôle de l’objet entier. Après avoir spécifié l’algorithme de somme de contrôle et le type de somme de contrôle de l’objet entier, vous pouvez fournir la valeur de somme de contrôle de cet objet pour le chargement partitionné.

Utilisation des sommes de contrôle au niveau des parties d’un chargement partitionné

Lorsque des objets sont chargés sur Amazon S3, ils peuvent être chargés en tant qu’objet unique ou en plusieurs parties par le biais du processus de chargement partitionné. Vous pouvez choisir un type de somme de contrôle pour votre chargement partitionné. Pour les sommes de contrôle au niveau de chaque partie d’un chargement partitionné (ou les sommes de contrôle composites), Amazon S3 calcule la somme de contrôle pour chaque partie en utilisant l’algorithme de somme de contrôle spécifié. Vous pouvez utiliser UploadPart pour fournir les valeurs de somme de contrôle pour chaque partie. Si l'objet que vous essayez de télécharger dans la console Amazon S3 est configuré pour utiliser l'algorithme de somme de contrôle CRC-64/NVME (CRC64NVME) et dépasse 16 Mo, il est automatiquement désigné comme somme de contrôle d'objet complète.

Amazon S3 utilise ensuite les valeurs de somme de contrôle stockées au niveau de chaque partie pour confirmer que chacune d’elle est correctement chargée. Lorsque la somme de contrôle de chaque partie (de l’objet entier) est fournie, S3 utilise les valeurs de la somme de contrôle stockées pour chaque partie afin de calculer la somme de contrôle de l’objet entier en interne, en la comparant à la valeur de la somme de contrôle fournie. Les coûts de calcul sont ainsi réduits, car S3 peut calculer une somme de contrôle de l’objet entier en utilisant la somme de contrôle de chaque partie. Pour en savoir plus sur les chargements partitionnés, consultez Chargement et copie d’objets à l’aide du chargement partitionné dans Amazon S3 et Utilisation des sommes de contrôle des objets entiers pour le chargement partitionné.

Lorsque l’objet est complètement chargé, vous pouvez utiliser la somme de contrôle finale calculée pour vérifier l’intégrité des données de l’objet.

Lors du chargement d’une partie du chargement partitionné, tenez compte des points suivants :

  • Pour extraire des informations sur l’objet, notamment le nombre de parties qui le composent, vous pouvez utiliser l’opération GetObjectAttributes. Avec les sommes de contrôle supplémentaires, vous pouvez également récupérer des informations pour chaque partie individuelle, y compris la valeur de la somme de contrôle de chaque partie.

  • Pour les chargements finalisés, vous pouvez obtenir la somme de contrôle d’une partie individuelle à l’aide des opérations GetObject ou HeadObject et en spécifiant un numéro de partie ou une plage d’octets qui correspond à sur une seule partie. Pour récupérer les valeurs de somme de contrôle de chaque partie des chargements partitionnés qui sont toujours en cours, vous pouvez utiliser ListParts.

  • En raison de la façon dont Amazon S3 calcule le total de contrôle pour les objets à plusieurs parties, la valeur du total de contrôle de l’objet peut changer si vous le copiez. Si vous utilisez un kit SDK ou l’API REST et que vous appelez CopyObject, Amazon S3 copie tout objet conformément aux limites de taille de l’opération API CopyObject. Amazon S3 effectue cette copie en une seule action, que l’objet ait été chargé en une seule requête ou dans le cadre d’un chargement partitionné. Avec une commande de copie, le total de contrôle de l’objet est un total de contrôle direct de l’objet complet. Si l’objet a été initialement chargé à l’aide d’un chargement partitionné, la valeur de la somme de contrôle change même si les données ne changent pas.

  • Les objets dont la taille dépasse les limites de l’opération d’API CopyObject doivent utiliser des commandes de copie par chargement partitionné.

  • Lorsque vous effectuez certaines opérations à l'aide du AWS Management Console, Amazon S3 utilise un téléchargement partitionné si la taille de l'objet est supérieure à 16 Mo.

Opérations de somme de contrôle

Après avoir chargé des objets, vous pouvez obtenir la valeur de la somme de contrôle et la comparer à une valeur de somme de contrôle précalculée ou précédemment stockée pour le même type d’algorithme. Les exemples suivants illustrent les opérations ou méthodes de somme de contrôle vous pouvez utiliser pour vérifier l’intégrité des données.

Pour en savoir plus sur l’utilisation de la console et la définition des algorithmes de somme de contrôle à utiliser lors du chargement d’objets, consultez Chargement d’objets et Didacticiel : Vérification de l’intégrité des données dans Amazon S3 avec des sommes de contrôle supplémentaires.

Pour en savoir plus sur l’utilisation de la console et la définition des algorithmes de somme de contrôle à utiliser lors du chargement d’objets, consultez Chargement d’objets et Didacticiel : Vérification de l’intégrité des données dans Amazon S3 avec des sommes de contrôle supplémentaires.

L'exemple suivant montre comment vous pouvez utiliser le AWS SDKs pour télécharger un fichier volumineux avec un téléchargement en plusieurs parties, télécharger un fichier volumineux et valider un fichier de téléchargement en plusieurs parties, le tout en utilisant SHA-256 pour la validation des fichiers.

Java
Exemple : chargement, téléchargement et vérification d’un fichier volumineux avec SHA-256

Pour obtenir des instructions sur la création et le test d'un échantillon de travail, voir Getting Started dans le guide du AWS SDK pour Java développeur.

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

L'exemple suivant montre comment vous pouvez utiliser le AWS SDKs pour télécharger un fichier volumineux avec un téléchargement en plusieurs parties, télécharger un fichier volumineux et valider un fichier de téléchargement en plusieurs parties, le tout en utilisant SHA-256 pour la validation des fichiers.

Java
Exemple : chargement, téléchargement et vérification d’un fichier volumineux avec SHA-256

Pour obtenir des instructions sur la création et le test d'un échantillon de travail, voir Getting Started dans le guide du AWS SDK pour Java développeur.

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(); } } }
Exemple : chargement, téléchargement et vérification d’un fichier volumineux avec SHA-256

Pour obtenir des instructions sur la création et le test d'un échantillon de travail, voir Getting Started dans le guide du AWS SDK pour Java développeur.

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

Vous pouvez envoyer des requêtes REST pour télécharger un objet avec une valeur de somme de contrôle afin de vérifier l'intégrité des PutObjectdonnées. Vous pouvez également récupérer la valeur de la somme de contrôle pour les objets à l'aide de GetObjectou HeadObject.

Vous pouvez envoyer des requêtes REST pour télécharger un objet avec une valeur de somme de contrôle afin de vérifier l'intégrité des PutObjectdonnées. Vous pouvez également récupérer la valeur de la somme de contrôle pour les objets à l'aide de GetObjectou HeadObject.

Vous pouvez envoyer une demande PUT pour télécharger un objet d’une taille maximale de 5 Go en une seule opération. Pour plus d’informations, reportez-vous à la section PutObject dans la Référence des commandes de l’AWS CLI . Vous pouvez également utiliser get-object et head-object pour récupérer le total de contrôle d’un objet déjà chargé afin de vérifier l’intégrité des données.

Pour plus d’informations, consultez la FAQ de l’interface de ligne de commande Amazon S3 dans le Guide de l’utilisateur AWS Command Line Interface .

Vous pouvez envoyer une demande PUT pour télécharger un objet d’une taille maximale de 5 Go en une seule opération. Pour plus d’informations, reportez-vous à la section PutObject dans la Référence des commandes de l’AWS CLI . Vous pouvez également utiliser get-object et head-object pour récupérer le total de contrôle d’un objet déjà chargé afin de vérifier l’intégrité des données.

Pour plus d’informations, consultez la FAQ de l’interface de ligne de commande Amazon S3 dans le Guide de l’utilisateur AWS Command Line Interface .

Utilisation de Content- MD5 lors du téléchargement d'objets

Une autre façon de vérifier l'intégrité de votre objet après le téléchargement consiste à fournir un MD5 résumé de l'objet lorsque vous le chargez. Si vous calculez le MD5 résumé de votre objet, vous pouvez le fournir avec la PUT commande en utilisant l'Content-MD5en-tête.

Après avoir chargé l'objet, Amazon S3 calcule le MD5 résumé de l'objet et le compare à la valeur que vous avez fournie. La requête n’aboutit que si les deux récapitulatifs correspondent.

Il n'est pas nécessaire de fournir un MD5 résumé, mais vous pouvez l'utiliser pour vérifier l'intégrité de l'objet dans le cadre du processus de téléchargement.

Utilisation du contenu MD5 et du ETag pour vérifier les objets téléchargés

La balise d'entité (ETag) d'un objet représente une version spécifique de cet objet. N'oubliez pas que cela reflète ETag uniquement les modifications apportées au contenu d'un objet, et non les modifications apportées à ses métadonnées. Si seules les métadonnées d'un objet changent, elles ETag restent les mêmes.

Selon l'objet, ETag l'objet peut être un MD5 condensé des données de l'objet :

  • Si un objet est créé par l'CopyObjectopération PutObjectPostObject, ou par le biais de AWS Management Console, et que cet objet est également en texte brut ou chiffré par chiffrement côté serveur avec des clés gérées Amazon S3 (SSE-S3), cet objet possède un ETag MD5 condensé de ses données d'objet.

  • Si un objet est créé par l'CopyObjectopération PutObjectPostObject, ou par le biais de AWS Management Console, et que cet objet est chiffré par chiffrement côté serveur avec des clés fournies par le client (SSE-C) ou par chiffrement côté serveur avec des clés () (SSE-KMS AWS KMS), cet objet possède un code qui n'est pas un ETag condensé de ses données d'objet. AWS Key Management Service MD5

  • Si un objet est créé soit par le processus de téléchargement en plusieurs parties, soit par l'UploadPartCopyopération, il ne ETag s'agit pas d'un MD5 condensé, quelle que soit la méthode de chiffrement utilisée. Si la taille d'un objet est supérieure à 16 Mo, il AWS Management Console télécharge ou copie cet objet sous forme de téléchargement partitionné ; il ne s'agit donc ETag pas d'un MD5 résumé.

Pour les objets dont le résumé ETag est le Content-MD5 condensé de l'objet, vous pouvez comparer la ETag valeur de l'objet avec un Content-MD5 résumé calculé ou précédemment stocké.

Utilisation des totaux de contrôle de fin

Lorsque vous chargez des objets sur Amazon S3, vous pouvez soit fournir une somme de contrôle précalculée pour l'objet, soit utiliser un AWS SDK pour créer automatiquement des sommes de contrôle de suivi pour les téléchargements fragmentés, en votre nom. Si vous utilisez une somme de contrôle finale, Amazon S3 génère automatiquement la somme de contrôle en utilisant l'algorithme que vous avez spécifié pour valider l'intégrité de l'objet dans les téléchargements fragmentés, lorsque vous chargez un objet.

Pour créer une somme de contrôle finale lors de l'utilisation d'un AWS SDK, renseignez le ChecksumAlgorithm paramètre avec votre algorithme préféré. Le SDK utilise cet algorithme pour calculer la somme de contrôle pour votre objet (ou des parties de l'objet) et l'ajoute automatiquement à la fin de votre demande de téléchargement segmentée. Ce comportement vous fait gagner du temps car Amazon S3 effectue la vérification et le chargement de vos données en une seule opération.

Important

Si vous utilisez S3 Object Lambda, toutes les requêtes adressées à S3 Object Lambda sont signées en utilisant s3-object-lambda au lieu de s3. Ce comportement affecte la signature des valeurs de total de contrôle de fin. Pour en savoir plus sur S3 Object Lambda, consultez Transformation d’objets avec S3 Object Lambda.

En-têtes de somme de contrôle suivants

Pour effectuer une demande de codage de contenu fragmenté, Amazon S3 exige que les serveurs clients incluent plusieurs en-têtes afin d'analyser correctement la demande. Les serveurs clients doivent inclure les en-têtes suivants :

  • x-amz-decoded-content-length: Cet en-tête indique la taille du texte brut des données réelles qui sont chargées sur Amazon S3 avec la demande.

  • x-amz-content-sha256: Cet en-tête indique le type de téléchargement fragmenté inclus dans la demande. Pour les téléchargements fragmentés avec des sommes de contrôle finales, la valeur d'en-tête est STREAMING-UNSIGNED-PAYLOAD-TRAILER destinée aux demandes qui n'utilisent pas la signature de charge utile et aux demandes qui utilisent la signature de charge utile STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER SigV4. (Pour plus d'informations sur l'implémentation de charges utiles signées, voir Calculs de signature pour l'en-tête d'autorisation : transfert d'une charge utile en plusieurs segments.)

  • x-amz-trailer: Cet en-tête indique le nom de l'en-tête final de la demande. S'il existe des sommes de contrôle finales (où AWS SDKs ajouter des sommes de contrôle aux corps de demande codés), la valeur d'x-amz-traileren-tête inclut le x-amz-checksum- préfixe et se termine par le nom de l'algorithme. Les x-amz-trailer valeurs suivantes sont actuellement prises en charge :

    • x-amz-checksum-crc32

    • x-amz-checksum-crc32c

    • x-amz-checksum-crc64nvme

    • x-amz-checksum-sha1

    • x-amz-checksum-sha256

Note

Vous pouvez également inclure l'Content-Encodingen-tête, avec la valeur segmentée, dans votre demande. Bien que cet en-tête ne soit pas obligatoire, son inclusion peut minimiser les problèmes de proxy HTTP lors de la transmission de données codées. Si un autre Content-Encoding en-tête (tel que gzip) existe dans la demande, l'Content-Encodingen-tête inclut la valeur segmentée dans une liste d'encodages séparés par des virgules. Par exemple, Content-Encoding: aws-chunked, gzip.

Pièces fragmentées

Lorsque vous chargez un objet sur Amazon S3 à l'aide d'un codage fragmenté, la demande de téléchargement inclut les types de fragments suivants (formatés dans l'ordre indiqué) :

  • Morceaux de corps d'objet : il peut y avoir un, plusieurs ou aucun fragment de corps associé à une demande de téléchargement fragmenté.

  • Morceaux d'achèvement : il peut y avoir un, plusieurs ou aucun segment de corps associé à une demande de téléchargement fragmenté.

  • Morceaux de fin : La somme de contrôle de fin est répertoriée après le segment de fin. Un seul morceau final est autorisé.

Note

Chaque téléchargement fragmenté doit se terminer par un CRLF final (tel que\r\n) pour indiquer la fin de la demande.

Pour des exemples de mise en forme fragmentée, consultezExemples : téléchargements fragmentés avec des sommes de contrôle.

Morceaux du corps de l'objet

Les fragments du corps de l'objet sont les fragments qui contiennent les données d'objet réelles qui sont téléchargées vers S3. Ces morceaux sont soumis à des contraintes de taille et de format cohérentes.

Taille du morceau du corps de l'objet

Ces fragments doivent contenir au moins 8 192 octets (ou 8 KiB) de données d'objet, à l'exception du dernier segment du corps, qui peut être plus petit. Il n'y a pas de taille maximale explicite, mais vous pouvez vous attendre à ce que tous les morceaux soient inférieurs à la taille de téléchargement maximale de 5 Go. La taille des fragments peut varier d'un morceau à l'autre en fonction de l'implémentation de votre serveur client.

Format de bloc du corps de l'objet

Les fragments de corps d'objet commencent par le codage hexadécimal du nombre d'octets qu'ils contiennent, suivi d'un CRLF (Carriage Return Line Feed), des octets de l'objet correspondant à ce segment et d'un autre CRLF.

Par exemple :

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

Toutefois, lorsque le fragment est signé, le segment du corps de l'objet suit un format différent, dans lequel la signature est ajoutée à la taille du bloc par un point-virgule. Par exemple :

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

Pour plus d'informations sur la signature fragmentée, voir Calculs de signature pour le Authorization En-tête : transfert d'une charge utile en plusieurs morceaux (AWS Signature Version 4). Pour plus d'informations sur le formatage des blocs, consultez la section Codage de transfert par blocs sur le site Web de l'éditeur RFC.

Morceaux de complétion

Les fragments d'achèvement doivent être le dernier fragment du corps de l'objet de chaque téléchargement fragmenté. Le format d'un segment de complétion est similaire à celui d'un segment de corps, mais il ne contient toujours aucun octet de données d'objet. (Le zéro octet de données d'objet indique que toutes les données ont été téléchargées.) Les téléchargements fragmentés doivent inclure un fragment d'achèvement comme dernier fragment du corps de l'objet, selon un format comme celui-ci :

0\r\n

Toutefois, si la demande de codage de contenu utilise la signature de charge utile, elle suit plutôt le format suivant :

0;chunk-signature\r\n

Morceaux de remorque

Les segments de bande-annonce contiennent la somme de contrôle calculée pour toutes les demandes de téléchargement S3. Les segments de bande-annonce incluent deux champs : un champ de nom d'en-tête et un champ de valeur d'en-tête. Le champ du nom d'en-tête d'une demande de téléchargement doit correspondre à la valeur transmise dans l'en-tête de la x-amz-trailer demande. Par exemple, si une demande contient le nom x-amz-trailer: x-amz-checksum-crc32 d'en-tête du fragment de la bande-annoncex-amz-checksum-sha1, la demande échoue. Le champ de valeur du fragment de bande-annonce inclut un codage base64 de la valeur de la somme de contrôle big-endian pour cet objet. (L'ordre big-endian stocke l'octet de données le plus significatif à l'adresse mémoire la plus basse et l'octet le moins significatif à la plus grande adresse mémoire). L'algorithme utilisé pour calculer cette somme de contrôle est le même que le suffixe du nom d'en-tête (par exemple,crc32).

Format des morceaux de la bande-annonce

Les segments de remorque utilisent le format suivant pour les demandes de charge utile non signées :

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

Pour les demandes contenant des charges utiles signées SigV4, le fragment de remorque inclut une signature de remorque après le morceau de remorque.

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

Vous pouvez également ajouter le CRLF directement à la fin de la valeur de la somme de contrôle base64. Par exemple :

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

Exemples : téléchargements fragmentés avec des sommes de contrôle

Amazon S3 prend en charge les téléchargements fragmentés qui utilisent le codage aws-chunked du contenu PutObject et les UploadPart demandes avec des sommes de contrôle ultérieures.

Exemple 1 — PutObject Demande fragmentée non signée avec une somme de contrôle CRC-32

Voici un exemple de PutObject demande segmentée avec une somme de contrôle CRC-32 à la fin. Dans cet exemple, le client télécharge un objet de 17 Ko en trois segments non signés et ajoute un bloc de somme de contrôle CRC-32 final en utilisant l'en-tête. x-amz-checksum-crc32

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

Voici un exemple de réponse :

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

L'utilisation du fil \n à la fin de la valeur de la somme de contrôle peut varier d'un client à l'autre.

Exemple 2 — PutObject Demande fragmentée signée SIGv4 avec une somme de contrôle CRC-32 () à la fin CRC32

Voici un exemple de PutObject demande segmentée avec une somme de contrôle CRC-32 à la fin. Cette demande utilise la signature de la charge utile SigV4. Dans cet exemple, le client télécharge un objet de 17 Ko en trois parties signées. En plus des object body morceaux, les completion chunk et trailer chunk sont également signés.

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

Voici un exemple de réponse :

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

Rubrique suivante :

Suppression d’objets

Rubrique précédente :

Téléchargement d’objets
ConfidentialitéConditions d'utilisation du sitePréférences de cookies
© 2025, Amazon Web Services, Inc. ou ses affiliés. Tous droits réservés.