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

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

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, exploitez les kits SDK AWS CLI ou AWS.

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 :

  • CRC64-NVME (Recommandé)

  • CRC-32

  • CRC-32C

  • SHA-1

  • SHA-256

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

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

  • Lorsque vous utilisez la AWS Management Console, sélectionnez 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, transmettez sa valeur au kit SDK AWS, qui l’inclura 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 kit SDK AWS mis à niveau, 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-64NVME.

  • 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 CRC64-NVME pour calculer la valeur de somme de contrôle de 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 Sommes de contrôle pour des sommes de contrôle composites (ou au niveau de chaque partie), les numéros de chaque partie du chargement partitionné doivent être consécutifs. 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é sous forme de chargement partitionné, sa balise d’entité n’est pas un condensé d’octets MD5 de l’objet entier. Amazon S3 calcule le condensé d’octets MD5 de chaque partie au fur et à mesure qu’elle est chargée. Les récapitulatifs MD5 sont utilisés pour déterminer la balise ETag de l’objet final. Amazon S3 concatène les octets des récapitulatifs MD5, puis calcule le récapitulatif MD5 de ces valeurs concaténées. Lors de l’étape finale de création de la balise d’entité, Amazon S3 ajoute à la fin un tiret avec le nombre total de parties.

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-64NVME : prend uniquement en charge le type d’algorithme d’objet entier.

  • CRC-32 : prend en charge à la fois les types d’algorithmes d’objets complets et les types d’algorithmes composites.

  • CRC-32C : prend en charge à la fois les types d’algorithmes d’objets complets et les types d’algorithmes composites.

  • SHA-1 : prend en charge à la fois les types d’algorithmes d’objets complets et les types d’algorithmes composites.

  • SHA-256 : prend en charge à la fois les types d’algorithmes 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-64NVME Oui Non
CRC-32 Oui Oui
CRC-32C Oui Oui
SHA-1 Non Oui
SHA-256 Non 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 la somme de contrôle d’un objet entier lors d’un chargement partitionné, le kit SDK AWS transmet cette somme de contrôle à Amazon S3, puis 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 d’un objet entier, vous pouvez utiliser les algorithmes de somme de contrôle CRC-64NVME, CRC-32 ou CRC-32C dans S3. 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 recommandé de somme de contrôle CRC-64NVME de l’objet complet à 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 charger dans la console Amazon S3 est configuré pour utiliser l’algorithme de somme de contrôle CRC-64NVME et qu’il dépasse 16 Mo, il est automatiquement désigné comme somme de contrôle d’objet entier.

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 de la fonction de la AWS Management Console, Amazon S3 utilise un 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.

L’exemple suivant montre comment utiliser les kits SDK AWS pour charger un fichier volumineux avec un chargement partitionné, télécharger un fichier volumineux et valider un fichier de chargement partitionné, le tout en utilisant SHA-256 pour la validation du fichier.

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

Pour obtenir les instructions pour la création et le test d’un exemple pratique, consultez Démarrer dans le Guide du développeur AWS SDK for Java.

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

Vous pouvez envoyer des requêtes REST pour charger un objet avec une valeur de total de contrôle pour vérifier l’intégrité des données avec PutObject. Vous pouvez également extraire la valeur de total de contrôle pour les objets à l’aide de la fonctionnalité GetObject ou 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.

Utilisation de Content-MD5 pour charger des objets

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

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

La fourniture d’un récapitulatif MD5 n’est pas obligatoire, mais vous pouvez l’utiliser pour vérifier l’intégrité de l’objet dans le cadre du processus de chargement.

Utilisation de Content-MD5 et de ETag pour vérifier les objets chargés.

Le balise d’entité (ETag) d’un objet représente une version spécifique de cet objet. Gardez à l’esprit que la balise d’entité ne reflète que les changements apportés au contenu d’un objet et non à ses métadonnées. Si seules les métadonnées d’un objet changent, la balise ETag reste le même.

Selon l’objet, la balise ETag de l’objet peut être un récapitulatif MD5 des données de l’objet :

  • Si un objet est créé par l’opération PutObject, PostObject, ou CopyObject, ou via la AWS Management Console et que cet objet est également en texte brut ou chiffré par un chiffrement côté serveur avec des clés gérées par Amazon S3 (SSE-S3), cet objet possède un ETag qui est un récapitulatif MD5 de ses données.

  • Si un objet est créé par l’opération PutObject, PostObject, ou CopyObject, ou par le AWS Management Console et que cet objet est chiffré par un chiffrement côté serveur avec des clés fournies par le client (SSE-C) ou un chiffrement côté serveur avec des clés AWS Key Management Service (AWS KMS) (SSE-KMS), cet objet a un ETag qui n’est pas un récapitulatif MD5 de ses données d’objet.

  • Si un objet est créé par le processus de chargement partitionné ou l’opération UploadPartCopy, sa balise d’entité n’est pas un condensé d’octets MD5, quelle que soit la méthode de chiffrement. Si un objet est plus grand que 16 Mo, le chargement AWS Management Console ou la copie de cet objet est un chargement partitionné et la balise ETag n’est pas un récapitulatif MD5.

Pour les objets où la balise ETag est le récapitulatif Content-MD5 de l’objet, vous pouvez comparer la valeur ETag de l’objet avec un récapitulatif Content-MD5 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 un total de contrôle précalculé pour l’objet, soit utiliser un kit SDK AWS pour créer automatiquement des totaux de contrôle de fin en votre nom. Si vous décidez d’utiliser une somme de contrôle de fin, 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 pendant le chargement.

Pour créer un total de contrôle de fin lors de l’utilisation d’un kit SDK AWS, remplissez le paramètre ChecksumAlgorithm avec votre algorithme préféré. Le kit SDK utilise cet algorithme pour calculer le total de contrôle de votre objet (ou de ses parties) et l’ajoute automatiquement à la fin de votre requête de chargement. 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.