Seleziona le tue preferenze relative ai cookie

Utilizziamo cookie essenziali e strumenti simili necessari per fornire il nostro sito e i nostri servizi. Utilizziamo i cookie prestazionali per raccogliere statistiche anonime in modo da poter capire come i clienti utilizzano il nostro sito e apportare miglioramenti. I cookie essenziali non possono essere disattivati, ma puoi fare clic su \"Personalizza\" o \"Rifiuta\" per rifiutare i cookie prestazionali.

Se sei d'accordo, AWS e le terze parti approvate utilizzeranno i cookie anche per fornire utili funzionalità del sito, ricordare le tue preferenze e visualizzare contenuti pertinenti, inclusa la pubblicità pertinente. Per continuare senza accettare questi cookie, fai clic su \"Continua\" o \"Rifiuta\". Per effettuare scelte più dettagliate o saperne di più, fai clic su \"Personalizza\".

Verifica dell'integrità degli oggetti in Amazon S3

Modalità Focus
Verifica dell'integrità degli oggetti in Amazon S3 - Amazon Simple Storage Service

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Amazon S3 utilizza valori di checksum per verificare l'integrità dei dati caricati o scaricati. Inoltre, puoi richiedere che venga calcolato un altro valore di checksum per qualsiasi oggetto da archiviare in Amazon S3. È possibile scegliere un algoritmo di checksum da utilizzare durante il caricamento, la copia o la copia in batch dei dati.

Quando si caricano i dati, Amazon S3 utilizza l'algoritmo scelto per calcolare un checksum sul lato server e lo convalida con il valore fornito prima di memorizzare l'oggetto e memorizzare il checksum come parte dei metadati dell'oggetto. Questa convalida funziona in modo coerente tra le modalità di crittografia, le dimensioni degli oggetti e le classi di storage per i caricamenti sia di una singola parte che di più parti. Quando si copiano o si copiano in batch i dati, tuttavia, Amazon S3 calcola il checksum sull'oggetto di origine e lo sposta nell'oggetto di destinazione.

Nota

Quando si esegue un caricamento di una singola parte o di più parti, è possibile includere facoltativamente un checksum precalcolato come parte della richiesta e utilizzare il tipo di checksum dell'oggetto completo. Per utilizzare valori precalcolati con più oggetti, usa o. AWS CLI AWS SDKs

Utilizzo di algoritmi di checksum supportati

Con Amazon S3, è possibile scegliere un algoritmo di checksum per convalidare i dati durante il caricamento. L'algoritmo di checksum specificato viene quindi memorizzato con l'oggetto e può essere usato per convalidare l'integrità dei dati durante i download. È possibile scegliere uno dei seguenti algoritmi di checksum Secure Hash Algorithms (SHA) o Cyclic Redundancy Check (CRC) per calcolare il valore di checksum:

  • CRC-64/NVME () CRC64NVME

  • CRC-32 () CRC32

  • CRC-32C () CRC32C

  • SHA-1 () SHA1

  • SHA256 () SHA256

Inoltre, puoi fornire un checksum per ogni richiesta utilizzando l'intestazione Content-. MD5

Quando si carica un oggetto, si specifica l'algoritmo che si desidera utilizzare:

  • Quando utilizzate il AWS Management Console, scegliete l'algoritmo di checksum che desiderate utilizzare. È possibile specificare facoltativamente il valore di checksum dell'oggetto. Quando Amazon S3 riceve l'oggetto, calcola il checksum utilizzando l'algoritmo specificato. Se i due valori di checksum non corrispondono, Amazon S3 genera un errore.

  • Quando si utilizza un SDK, tieni presente quanto segue:

    • Imposta il parametro ChecksumAlgorithm sull'algoritmo da utilizzare per Amazon S3. Se disponi già di un checksum precalcolato, trasmetti il valore del checksum all' AWS SDK e l'SDK lo include nella richiesta. Se non si trasmette un valore di checksum o non si specifica un algoritmo di checksum, l'SDK calcola automaticamente un valore di checksum per l'utente e lo include nella richiesta per garantire la protezione dell'integrità. Se il valore del checksum individuale non corrisponde al valore impostato dell'algoritmo di checksum, Amazon S3 respinge la richiesta con un errore BadDigest.

    • Se utilizzi un SDK aggiornato, l' AWS SDK sceglie un algoritmo di checksum per te. Tuttavia, è possibile ignorare questo algoritmo di checksum.

    • Se non specifichi un algoritmo di checksum e l'SDK non calcola nemmeno un checksum per te, S3 sceglie automaticamente l'algoritmo di checksum CRC-64/NVME (). CRC64NVME

  • Quando utilizzi la REST API, non utilizzare il parametro x-amz-sdk-checksum-algorithm. Utilizza invece una delle intestazioni specifiche dell'algoritmo (ad esempio, x-amz-checksum-crc32).

Per applicare uno di questi valori di checksum a oggetti già caricati su Amazon S3, è possibile copiare l'oggetto e specificare se si desidera utilizzare l'algoritmo di checksum esistente o uno nuovo. Se non si specifica un algoritmo, S3 utilizza l'algoritmo esistente. Se l'oggetto di origine non ha un algoritmo di checksum o un valore di checksum specificato, Amazon S3 utilizza l'algoritmo CRC-64/NVME per calcolare il valore di checksum per l'oggetto di destinazione. È inoltre possibile specificare un algoritmo di checksum quando si copiano gli oggetti utilizzando le Operazioni in batch S3.

Importante

Se utilizzi un caricamento in più parti con checksum per checksum compositi (o a livello di parte), i numeri di parte per il caricamento multiparte devono essere consecutivi e iniziare con 1. Se si tenta di completare una richiesta di caricamento multiparte con numeri di parte non consecutivi, Amazon S3 genera un errore HTTP 500 Internal Server.

Tipi di checksum di oggetti completi e compositi

In Amazon S3, esistono due tipi di checksum supportati:

  • Checksum di oggetti completi: un checksum dell'oggetto completo viene calcolato sulla base di tutto il contenuto di un caricamento multiparte, coprendo tutti i dati dal primo byte della prima parte all'ultimo byte dell'ultima parte.

    Nota

    Tutte le richieste PUT richiedono un tipo di checksum dell'oggetto completo.

  • Checksum compositi: un checksum composito viene calcolato in base ai singoli checksum di ciascuna parte di un caricamento multiparte. Invece di calcolare un checksum basato su tutto il contenuto dei dati, questo approccio aggrega i checksum a livello di parte (dalla prima all'ultima parte) per produrre un singolo checksum combinato per l'oggetto completo.

    Nota

    Quando un oggetto viene caricato come caricamento in più parti, il tag di entità (ETag) per l'oggetto non è un riassunto dell'intero oggetto. MD5 Invece, Amazon S3 calcola il MD5 digest di ogni singola parte man mano che viene caricata. I MD5 digest vengono utilizzati per determinare l'oggetto finale ETag . Amazon S3 concatena i byte per i digest e quindi calcola il MD5 digest di questi valori concatenati. MD5 Durante la fase finale di ETag creazione, Amazon S3 aggiunge un trattino con il numero totale di parti alla fine.

Amazon S3 supporta i seguenti tipi di algoritmi di checksum completi e compositi:

  • CRC-64/NVME (CRC64NVME): supporta solo il tipo di algoritmo a oggetti completo.

  • CRC-32 (CRC32): supporta sia i tipi di algoritmi a oggetti completi che quelli compositi.

  • CRC-32C (CRC32C): supporta sia i tipi di algoritmi a oggetti completi che quelli compositi.

  • SHA-1 (SHA1): supporta sia i tipi di algoritmi a oggetti completi che quelli compositi.

  • SHA-256 (SHA256): supporta sia i tipi di algoritmi a oggetti completi che quelli compositi.

Caricamenti di una singola parte

I checksum degli oggetti caricati in una singola parte (usando il metodo PutObject) sono trattati come checksum completi dell'oggetto. Quando si carica un oggetto nella console di Amazon S3, è possibile scegliere l'algoritmo di checksum che si desidera che S3 utilizzi e anche (facoltativamente) fornire un valore precompilato. Amazon S3 convalida quindi questo checksum prima di memorizzare l'oggetto e il suo valore di checksum. È possibile verificare l'integrità dei dati di un oggetto quando si richiede il valore di checksum durante il download degli oggetti.

Caricamenti in più parti

Quando si carica l'oggetto in più parti utilizzando l'API MultipartUpload è possibile specificare l'algoritmo di checksum che si desidera utilizzare su Amazon S3 e il tipo di checksum (oggetto completo o composito).

La tabella seguente indica quale tipo di algoritmo di checksum è supportato per ogni algoritmo di checksum in un caricamento multiparte:

Algoritmo di checksum Oggetto completo Composita
CRC-64/NVME () CRC64NVME No
CRC-32 () CRC32
CRC-32C () CRC32C
SHA-1 () SHA1
SHA256 () SHA256

Utilizzo di checksum completi degli oggetti per il caricamento multiparte

Quando si crea o si esegue un caricamento multiparte, è possibile utilizzare checksum completi degli oggetti per la convalida del caricamento. Ciò significa che è possibile fornire l'algoritmo di checksum per l'API MultipartUpload semplificando gli strumenti di validazione dell'integrità, perché non è più necessario tracciare vincoli di parti per oggetti caricati. È possibile fornire il checksum dell'intero oggetto nella richiesta CompleteMultipartUpload insieme alla dimensione dell'oggetto.

Quando fornisci un checksum completo dell'oggetto durante un caricamento in più parti, l' AWS SDK trasmette il checksum ad Amazon S3 e S3 convalida l'integrità dell'oggetto lato server, confrontandola con il valore ricevuto. Quindi, Amazon S3 memorizza l'oggetto se i valori corrispondono. Se i due valori non coincidono, S3 respinge la richiesta con un errore BadDigest. Il checksum dell'oggetto viene memorizzato anche nei metadati dell'oggetto, che verranno utilizzati in seguito per convalidare l'integrità dei dati di un oggetto.

Per i checksum completi degli oggetti, puoi utilizzare gli algoritmi di checksum CRC-64/NVME (), CRC-32 () o CRC-32C () in S3. CRC64NVME CRC32 CRC32C I checksum completi degli oggetti nei caricamenti multiparte sono disponibili solo per i checksum basati su CRC perché possono linearizzarsi in un checksum completo dell'oggetto. Questa linearizzazione consente ad Amazon S3 di parallelizzare le richieste per migliorare le prestazioni. In particolare, S3 può calcolare il checksum dell'intero oggetto a partire dai checksum a livello di parte. Questo tipo di convalida non è disponibile per altri algoritmi, come SHA e. MD5 Poiché S3 dispone di protezioni di integrità predefinite, se gli oggetti vengono caricati senza un checksum, S3 allega automaticamente all'oggetto l'algoritmo di checksum CRC-64/NVME () per l'intero oggetto consigliato. CRC64NVME

Nota

Per avviare il caricamento multiparte, è possibile specificare l'algoritmo di checksum e il tipo di checksum dell'oggetto completo. Dopo aver specificato l'algoritmo di checksum e il tipo di checksum dell'oggetto completo, è possibile fornire il valore di checksum dell'oggetto completo per il caricamento multiparte.

Utilizzo di checksum a livello di parte per il caricamento multiparte

Quando gli oggetti vengono caricati su Amazon S3, possono essere caricati come un singolo oggetto o in parti con il processo di caricamento multiparte. È possibile scegliere un tipo di checksum per il caricamento multiparte. Per i checksum a livello di parte di caricamento multiparte (o checksum compositi), Amazon S3 calcola il checksum per ogni singola parte utilizzando l'algoritmo di checksum specificato. È possibile utilizzare UploadPart per fornire i valori di checksum per ogni parte. Se l'oggetto che tenti di caricare nella console Amazon S3 è impostato per utilizzare l'algoritmo di checksum CRC-64/NVME (CRC64NVME) e supera i 16 MB, viene automaticamente designato come checksum completo dell'oggetto.

Amazon S3 utilizza quindi i valori di checksum memorizzati a livello di parte per confermare che ogni parte è stata caricata correttamente. Quando viene fornito il checksum di ogni parte (per l'intero oggetto), S3 utilizza i valori di checksum memorizzati di ogni parte per calcolare internamente il checksum dell'intero oggetto, confrontandolo con il valore di checksum fornito. Questo riduce al minimo i costi di calcolo, poiché S3 può calcolare un checksum dell'intero oggetto utilizzando il checksum delle parti. Per ulteriori informazioni sui caricamenti multiparte, consulta Caricamento e copia di oggetti utilizzando il caricamento multiparte in Amazon S3 e Utilizzo di checksum completi degli oggetti per il caricamento multiparte.

Quando l'oggetto è stato completamente caricato, è possibile utilizzare il checksum finale calcolato per verificare l'integrità dei dati dell'oggetto.

Quando si carica una parte del caricamento multiparte, tieni presente quanto segue:

  • Per recuperare informazioni sull'oggetto, compreso il numero di parti che compongono l'intero oggetto, si può usare l'operazione GetObjectAttributes. Con i checksum aggiuntivi, è possibile recuperare anche le informazioni per ogni singolo componente, che includono il valore del checksum del componente.

  • Per i caricamenti completati, è possibile ottenere la somma di controllo di una singola parte utilizzando i tasti GetObject o HeadObject e specificando un numero di parte o un intervallo di byte che corrisponde a una singola parte. Se si desidera recuperare i valori di checksum per le singole parti dei caricamenti multiparte che sono ancora in corso, si può usare ListParts.

  • A causa del modo in cui Amazon S3 calcola il checksum per gli oggetti in più parti, il valore del checksum dell'oggetto potrebbe cambiare se lo si copia. Se si utilizza un SDK o la REST API e si chiama CopyObject, Amazon S3 copia qualsiasi oggetto fino alle limitazioni di dimensione dell'operazione dell'API CopyObject. Amazon S3 esegue questa copia come un'unica operazione, indipendentemente dal fatto che l'oggetto sia stato caricato in una singola richiesta o come parte di un caricamento in più parti. Con il comando copy, il checksum dell'oggetto è un checksum diretto dell'oggetto completo. Se l'oggetto è stato originariamente caricato con un caricamento multiparte, il valore del checksum cambia anche se i dati non cambiano.

  • Gli oggetti di dimensioni superiori alle limitazioni di dimensione dell'operazione API CopyObject devono utilizzare comandi di copia di caricamento multiparte.

  • Quando esegui alcune operazioni utilizzando AWS Management Console, Amazon S3 utilizza un caricamento in più parti se l'oggetto ha una dimensione superiore a 16 MB.

Operazioni di checksum

Dopo aver caricato gli oggetti, è possibile ottenere il valore di checksum e confrontarlo con un valore di checksum precalcolato o precedentemente memorizzato dello stesso tipo di algoritmo. Gli esempi seguenti mostrano quali operazioni o metodi di checksum si possono usare per verificare l'integrità dei dati.

Per ulteriori informazioni sull'utilizzo della console e sulla specifica degli algoritmi di checksum da utilizzare durante il caricamento degli oggetti, consultare Caricamento degli oggetti e Tutorial: Verifica dell'integrità dei dati in Amazon S3 con checksum aggiuntivi.

Per ulteriori informazioni sull'utilizzo della console e sulla specifica degli algoritmi di checksum da utilizzare durante il caricamento degli oggetti, consultare Caricamento degli oggetti e Tutorial: Verifica dell'integrità dei dati in Amazon S3 con checksum aggiuntivi.

L'esempio seguente mostra come è possibile utilizzare AWS SDKs per caricare un file di grandi dimensioni con caricamento in più parti, scaricare un file di grandi dimensioni e convalidare un file di caricamento composto da più parti, il tutto utilizzando SHA-256 per la convalida dei file.

Java
Esempio: caricamento, download e verifica di un file di grandi dimensioni con SHA-256

Per istruzioni su come creare e testare un esempio funzionante, consulta Getting Started nella Developer Guide. 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(); } } }

L'esempio seguente mostra come è possibile utilizzare AWS SDKs per caricare un file di grandi dimensioni con caricamento in più parti, scaricare un file di grandi dimensioni e convalidare un file di caricamento composto da più parti, il tutto utilizzando SHA-256 per la convalida dei file.

Java
Esempio: caricamento, download e verifica di un file di grandi dimensioni con SHA-256

Per istruzioni su come creare e testare un esempio funzionante, consulta Getting Started nella Developer Guide. 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(); } } }
Esempio: caricamento, download e verifica di un file di grandi dimensioni con SHA-256

Per istruzioni su come creare e testare un esempio funzionante, consulta Getting Started nella Developer Guide. 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(); } } }

Puoi inviare richieste REST per caricare un oggetto con un valore di checksum con PutObjectcui verificare l'integrità dei dati. Puoi anche recuperare il valore di checksum per gli oggetti utilizzando o. GetObjectHeadObject

Puoi inviare richieste REST per caricare un oggetto con un valore di checksum con PutObjectcui verificare l'integrità dei dati. Puoi anche recuperare il valore di checksum per gli oggetti utilizzando o. GetObjectHeadObject

È possibile inviare una richiesta PUT per caricare un oggetto di un massimo di 5 GB in una singola operazione. Per ulteriori informazioni, consulta PutObject nella Documentazione di riferimento per i comandi di AWS CLI . Puoi utilizzare anche get-object e head-object per recuperare il checksum di un oggetto già caricato per verificare l'integrità dei dati.

Per informazioni, consulta le Domande frequenti sulla CLI di Amazon S3 nella Guida all'utente AWS Command Line Interface .

È possibile inviare una richiesta PUT per caricare un oggetto di un massimo di 5 GB in una singola operazione. Per ulteriori informazioni, consulta PutObject nella Documentazione di riferimento per i comandi di AWS CLI . Puoi utilizzare anche get-object e head-object per recuperare il checksum di un oggetto già caricato per verificare l'integrità dei dati.

Per informazioni, consulta le Domande frequenti sulla CLI di Amazon S3 nella Guida all'utente AWS Command Line Interface .

Utilizzo del contenuto: MD5 durante il caricamento di oggetti

Un altro modo per verificare l'integrità dell'oggetto dopo il caricamento consiste nel fornire un MD5 riepilogo dell'oggetto al momento del caricamento. Se si calcola il MD5 digest dell'oggetto, è possibile fornire al digest il PUT comando utilizzando l'intestazione. Content-MD5

Dopo aver caricato l'oggetto, Amazon S3 calcola MD5 il digest dell'oggetto e lo confronta con il valore che hai fornito. La richiesta ha esito positivo solo se i due digest corrispondono.

Non è necessario fornire un MD5 digest, ma puoi utilizzarlo per verificare l'integrità dell'oggetto come parte del processo di caricamento.

Utilizzo di Content- MD5 and the ETag per verificare gli oggetti caricati

Il tag di entità (ETag) per un oggetto rappresenta una versione specifica di quell'oggetto. Tieni presente che riflette ETag solo le modifiche al contenuto di un oggetto, non le modifiche ai relativi metadati. Se cambiano solo i metadati di un oggetto, ETag rimangono gli stessi.

A seconda dell'oggetto, l' ETag oggetto potrebbe essere un MD5 riassunto dei dati dell'oggetto:

  • Se un oggetto viene creato dall'CopyObjectoperazione PutObjectPostObject, o o tramite la AWS Management Console, e tale oggetto è anche in testo semplice o crittografato mediante crittografia lato server con chiavi gestite di Amazon S3 (SSE-S3), quell'oggetto dispone di un ETag riepilogo dei relativi dati oggetto. MD5

  • Se un oggetto viene creato dall'CopyObjectoperazione PutObjectPostObject, o tramite la AWS Management Console, e tale oggetto è crittografato mediante crittografia lato server con chiavi fornite dal cliente (SSE-C) o crittografia lato server con chiavi AWS Key Management Service (AWS KMS) (SSE-KMS), quell'oggetto ha un oggetto ETag che non è un MD5 riepilogo dei suoi dati oggetto.

  • Se un oggetto viene creato mediante il processo di caricamento multiparte o l'UploadPartCopyoperazione, quello dell'oggetto non ETag è un MD5 digest, indipendentemente dal metodo di crittografia. Se un oggetto è più grande di 16 MB, AWS Management Console carica o copia quell'oggetto come caricamento in più parti e quindi ETag non è un digest. MD5

Per gli oggetti in cui ETag è il riassunto dell'oggetto, potete confrontare il ETag valore dell'oggetto con un Content-MD5 digest calcolato o precedentemente memorizzato. Content-MD5

Utilizzo dei checksum finali

Quando carichi oggetti su Amazon S3, puoi fornire un checksum precalcolato per l'oggetto o utilizzare AWS un SDK per creare automaticamente checksum finali per caricamenti in blocchi, per tuo conto. Se utilizzi un checksum finale, Amazon S3 genera automaticamente il checksum utilizzando l'algoritmo specificato per convalidare l'integrità dell'oggetto nei caricamenti in blocchi, quando carichi un oggetto.

Per creare un checksum finale quando usi un SDK, compila il parametro con il tuo algoritmo preferito AWS . ChecksumAlgorithm L'SDK utilizza tale algoritmo per calcolare il checksum dell'oggetto (o delle parti dell'oggetto) e lo aggiunge automaticamente alla fine della richiesta di caricamento suddivisa in blocchi. Questo comportamento ti consente di risparmiare tempo perché Amazon S3 esegue sia la verifica che il caricamento dei tuoi dati in un unico passaggio.

Importante

Se utilizzi S3 Object Lambda, tutte le richieste a S3 Object Lambda vengono firmate tramite s3-object-lambda anziché s3. Questo comportamento influisce sulla firma dei valori di checksum finali. Per ulteriori informazioni su Lambda per oggetti S3, consulta Trasformazione di oggetti con S3 Object Lambda.

Intestazioni di checksum finali

Per effettuare una richiesta di codifica del contenuto in blocchi, Amazon S3 richiede che i server client includano diverse intestazioni per analizzare correttamente la richiesta. I server client devono includere le seguenti intestazioni:

  • x-amz-decoded-content-length: questa intestazione indica la dimensione in chiaro dei dati effettivi che vengono caricati su Amazon S3 con la richiesta.

  • x-amz-content-sha256: Questa intestazione indica il tipo di caricamento suddiviso in blocchi incluso nella richiesta. Per i caricamenti in blocchi con checksum finali, il valore dell'intestazione si riferisce alle richieste che non utilizzano la firma del payload e alle STREAMING-UNSIGNED-PAYLOAD-TRAILER richieste che utilizzano la firma del payload SigV4. STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER (Per ulteriori informazioni sull'implementazione dei payload firmati, consulta Calcoli della firma per l'intestazione di autorizzazione: trasferimento di un payload in più blocchi.)

  • x-amz-trailer: Questa intestazione indica il nome dell'intestazione finale nella richiesta. Se esistono checksum finali (dove AWS SDKs aggiungere checksum ai corpi codificati della richiesta), il valore dell'x-amz-trailerintestazione include il prefisso e termina con il nome dell'algoritmo. x-amz-checksum- x-amz-trailerAttualmente sono supportati i seguenti valori:

    • x-amz-checksum-crc32

    • x-amz-checksum-crc32c

    • x-amz-checksum-crc64nvme

    • x-amz-checksum-sha1

    • x-amz-checksum-sha256

Nota

Puoi anche includere l'Content-Encodingintestazione, con il valore suddiviso in blocchi, nella tua richiesta. Sebbene questa intestazione non sia obbligatoria, l'inclusione di questa intestazione può ridurre al minimo i problemi del proxy HTTP durante la trasmissione di dati codificati. Se nella richiesta è presente un'altra Content-Encoding intestazione (come gzip), l'intestazione include il valore suddiviso in blocchi in un elenco di Content-Encoding codifiche separate da virgole. Ad esempio Content-Encoding: aws-chunked, gzip.

Parti suddivise in blocchi

Quando carichi un oggetto su Amazon S3 utilizzando la codifica in blocchi, la richiesta di caricamento include i seguenti tipi di blocchi (formattati nell'ordine elencato):

  • Blocchi del corpo dell'oggetto: a una richiesta di caricamento suddivisa in blocchi possono essere associati uno, più o zero blocchi del corpo.

  • Blocchi di completamento: a una richiesta di caricamento suddivisa in blocchi possono essere associati uno, più o zero blocchi del corpo.

  • Blocchi finali: il checksum finale viene elencato dopo il blocco di completamento. È consentito un solo blocco finale.

Nota

Ogni caricamento suddiviso in blocchi deve terminare con un CRLF finale (ad esempio\r\n) per indicare la fine della richiesta.

Per esempi di formattazione in blocchi, vedi. Esempi: caricamenti suddivisi in blocchi con checksum finali

Blocchi del corpo dell'oggetto

I blocchi del corpo dell'oggetto sono i blocchi che contengono i dati effettivi dell'oggetto che vengono caricati su S3. Questi blocchi hanno vincoli di dimensione e formato coerenti.

Dimensione del blocco del corpo dell'oggetto

Questi blocchi devono contenere almeno 8.192 byte (o 8 KB) di dati oggetto, ad eccezione del blocco del corpo finale, che può essere più piccolo. Non esiste una dimensione massima esplicita dei blocchi, ma puoi aspettarti che tutti i blocchi siano inferiori alla dimensione massima di caricamento di 5 GB. Le dimensioni dei blocchi possono variare da un blocco all'altro in base all'implementazione del server client.

Formato del blocco del corpo dell'oggetto

I blocchi del corpo dell'oggetto iniziano con la codifica esadecimale del numero di byte nel blocco del corpo dell'oggetto, seguita da un CRLF (Carriage Return Line Feed), dai byte dell'oggetto per quel blocco e da un altro CRLF.

Per esempio:

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

Tuttavia, quando il blocco è firmato, il blocco del corpo dell'oggetto segue un formato diverso, in cui la firma viene aggiunta alla dimensione del blocco con un delimitatore di punto e virgola. Per esempio:

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

Per ulteriori informazioni sulla firma in blocchi, consulta Calcoli della firma per Authorization Intestazione: trasferimento di un payload in più blocchi (Signature versione 4).AWS Per ulteriori informazioni sulla formattazione dei blocchi, vedere Chunked transfer encoding sul sito Web di RFC Editor.

Blocchi di completamento

I blocchi di completamento devono essere il blocco finale del corpo dell'oggetto di ogni caricamento suddiviso in blocchi. Il formato di un blocco di completamento è simile a quello del blocco del corpo, ma contiene sempre zero byte di dati relativi all'oggetto. (Gli zero byte dei dati dell'oggetto indicano che tutti i dati sono stati caricati.) I caricamenti in blocchi devono includere un blocco di completamento come blocco finale del corpo dell'oggetto, secondo un formato come questo:

0\r\n

Tuttavia, se la richiesta di codifica del contenuto utilizza la firma del payload, segue invece questo formato:

0;chunk-signature\r\n

Pezzi del rimorchio

I blocchi del trailer contengono il checksum calcolato per tutte le richieste di caricamento su S3. I blocchi di trailer includono due campi: un campo con il nome dell'intestazione e un campo con il valore dell'intestazione. Il campo del nome dell'intestazione per una richiesta di caricamento deve corrispondere al valore passato nell'intestazione della richiesta. x-amz-trailer Ad esempio, se una richiesta contiene x-amz-trailer: x-amz-checksum-crc32 e il blocco del trailer ha il nome dell'intestazionex-amz-checksum-sha1, la richiesta ha esito negativo. Il campo value nel blocco trailer include una codifica base64 del valore di checksum big-endian per quell'oggetto. (L'ordinamento big-endian memorizza il byte di dati più importante all'indirizzo di memoria più basso e il byte meno significativo all'indirizzo di memoria più grande). L'algoritmo utilizzato per calcolare questo checksum è lo stesso del suffisso per il nome dell'intestazione (ad esempio,). crc32

Formato Trailer Chunk

I blocchi di trailer utilizzano il seguente formato per le richieste di payload non firmate:

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

Per le richieste con payload firmati SigV4, il trailer chunk include una firma del trailer dopo il blocco del trailer.

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

Puoi anche aggiungere il CRLF direttamente alla fine del valore di checksum base64. Per esempio:

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

Esempi: caricamenti suddivisi in blocchi con checksum finali

Amazon S3 supporta caricamenti in blocchi che utilizzano la codifica aws-chunked dei contenuti e le richieste con checksum finali. PutObject UploadPart

Esempio 1 — Richiesta suddivisa in blocchi non firmata con checksum CRC-32 finale PutObject

Di seguito è riportato un esempio di richiesta suddivisa in blocchi con un checksum CRC-32 finalePutObject. In questo esempio, il client carica un oggetto da 17 KB in tre blocchi non firmati e aggiunge un blocco di checksum CRC-32 finale utilizzando l'intestazione. 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

Ecco un esempio di risposta:

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

L'utilizzo del linefeed alla fine del valore del checksum può variare \n tra i client.

Esempio 2 — PutObject Richiesta frammentata firmata da SigV4 con un checksum CRC-32 () finale CRC32

Di seguito è riportato un esempio di richiesta suddivisa in blocchi con un checksum CRC-32 finale. PutObject Questa richiesta utilizza la firma del payload SigV4. In questo esempio, il client carica un oggetto da 17 KB in tre blocchi firmati. Oltre ai blocchi, vengono object body firmati anche i completion chunk e. trailer chunk

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

Ecco un esempio di risposta:

HTTP/1.1 200 ETag: ETag x-amz-checksum-crc32: YABb/g==
PrivacyCondizioni del sitoPreferenze cookie
© 2025, Amazon Web Services, Inc. o società affiliate. Tutti i diritti riservati.