web-dev-qa-db-fra.com

Comment obtenir la somme md5 d'un fichier sur le S3 d'Amazon

Si j'ai des fichiers existants sur le S3 d'Amazon, quel est le moyen le plus simple d'obtenir leur somme md5 sans devoir télécharger les fichiers?

Merci

53
Switch

Hmm ... Je pense que vous pouvez regarder l'en-tête de l'ETag. (dans ce cas, vous pouvez utiliser la méthode HTTP HEAD plutôt que GET.) Ils ne le disent pas tout à fait explicitement, mais il est presque certain que Amazon utilise le hachage MD5 pour l'ETag. Depuis la Documentation PUT Object (ne sait pas pourquoi ils ne se contentent pas de le dire et de le dire):

Pour vous assurer que les données ne sont pas corrompues sur le réseau, utilisez l'en-tête Content-MD5. Lorsque vous utilisez l'en-tête Content-MD5, Amazon S3 compare l'objet à la valeur MD5 fournie. Si elles ne correspondent pas, Amazon S3 renvoie une erreur. De plus, vous pouvez calculer le MD5 en plaçant un objet dans Amazon S3 et comparer l'Etag renvoyé à la valeur MD5 calculée.

De plus, les méthodes SOAP vous permettent de demander uniquement les métadonnées et non les données elles-mêmes.

37
Jason S

ETag ne semble pas être MD5 pour les téléchargements en plusieurs parties (selon le commentaire de Gael Fraiteur). Dans ces cas, il contient un suffixe de moins et un nombre. Cependant, même le bit avant le moins ne semble pas être le MD5, même s'il a la même longueur qu'un MD5. Peut-être le suffixe est le nombre de pièces téléchargées?

22
Duncan Harris

La documentation d'AWS sur ETag indique: 

La balise entity est un hachage de l'objet. La balise ETag reflète uniquement les modifications apportées au contenu d'un objet, pas ses métadonnées. ETag peut être ou non un condensé MD5 des données de l'objet. Cela dépend de la manière dont l'objet a été créé et de son cryptage, comme décrit ci-dessous:

  • Les objets créés par l'objet PUT, l'objet POST, ou l'opération de copie, ou via AWS Management Console, et chiffrés par SSE-S3 ou par un texte en clair, ont des balises ETags qui sont un condensé MD5 de leurs données d'objet.
  • Les objets créés par l'objet PUT, l'objet POST, ou l'opération de copie, ou via AWS Management Console, et chiffrés par SSE-C ou SSE-KMS, ont des balises ETags qui ne sont pas un résumé MD5 de leurs données d'objet.
  • Si un objet est créé à l'aide de l'opération de téléchargement en plusieurs parties ou de la copie partielle, l'ETag n'est pas un résumé MD5, quelle que soit la méthode de cryptage.

Référence: http://docs.aws.Amazon.com/AmazonS3/latest/API/RESTCommonResponseHeaders.html

17
Dennis Wu

Pour tous ceux qui passent du temps à chercher autour pour découvrir que pourquoi le md5 n'est pas le même que ETag dans S3.

ETag calculera par rapport au bloc de données et enchaînera tous les md5hash pour faire de nouveau hachage md5 et conserver le nombre de chunk à la fin.

Voici la version C # pour générer du hachage

    string etag = HashOf("file.txt",8);

code source

    private string HashOf(string filename,int chunkSizeInMb)
    {
        string returnMD5 = string.Empty;
        int chunkSize = chunkSizeInMb * 1024 * 1024;

        using (var crypto = new MD5CryptoServiceProvider())
        {
            int hashLength = crypto.HashSize/8;

            using (var stream = File.OpenRead(filename))
            {
                if (stream.Length > chunkSize)
                {
                    int chunkCount = (int)Math.Ceiling((double)stream.Length/(double)chunkSize);

                    byte[] hash = new byte[chunkCount*hashLength];
                    Stream hashStream = new MemoryStream(hash);

                    long nByteLeftToRead = stream.Length;
                    while (nByteLeftToRead > 0)
                    {
                        int nByteCurrentRead = (int)Math.Min(nByteLeftToRead, chunkSize);
                        byte[] buffer = new byte[nByteCurrentRead];
                        nByteLeftToRead -= stream.Read(buffer, 0, nByteCurrentRead);

                        byte[] tmpHash = crypto.ComputeHash(buffer);

                        hashStream.Write(tmpHash, 0, hashLength);

                    }

                    returnMD5 = BitConverter.ToString(crypto.ComputeHash(hash)).Replace("-", string.Empty).ToLower()+"-"+ chunkCount;
                }
                else {
                    returnMD5 = BitConverter.ToString(crypto.ComputeHash(stream)).Replace("-", string.Empty).ToLower();

                }
                stream.Close();
            }
        }
        return returnMD5;
    }
4
Pitipong Guntawong

J'ai recoupé jets3t et la console de gestion avec le MD5sum des fichiers téléchargés et ETag semble être égal à MD5sum. Vous pouvez simplement afficher les propriétés du fichier dans AWS Management Console: 

https://console.aws.Amazon.com/s3/home

1
b10y

J'ai trouvé que s3cmd a une option --list-md5 qui peut être utilisée avec la commande ls, par exemple.

s3cmd ls --list-md5 s3://bucket_of_mine/

J'espère que cela t'aides.

1
ahnkle

Cela fonctionne pour moi . En PHP, vous pouvez comparer la somme de contrôle entre le fichier local et le fichier Amazon en utilisant ceci:



    // get localfile md5
    $checksum_local_file = md5_file ( '/home/file' );

    // compare checksum between localfile and s3file    
    public function compareChecksumFile($file_s3, $checksum_local_file) {

        $Connection = new AmazonS3 ();
        $bucket = Amazon_bucket;
        $header = $Connection->get_object_headers( $bucket, $file_s3 );

        // get header
        if (empty ( $header ) || ! is_object ( $header )) {
            throw new RuntimeException('checksum error');
        }
        $head = $header->header;
        if (empty ( $head ) || !is_array($head)) {
            throw new RuntimeException('checksum error');
        }
        // get etag (md5 Amazon)
        $etag = $head['etag'];
        if (empty ( $etag )) {
            throw new RuntimeException('checksum error');
        }
        // remove quotes
        $checksumS3 = str_replace('"', '', $etag);

        // compare md5
        if ($checksum_local_file === $checksumS3) {
            return TRUE;
        } else {
            return FALSE;
        }
    }

0

Voici le code permettant de convertir l'ETag S3 d'un objet dans PowerShell à partir de c #.

function Get-ETag {
  [CmdletBinding()]
  param(
    [Parameter(Mandatory=$true)]
    [string]$Path,
    [Parameter(Mandatory=$true)]
    [int]$ChunkSizeInMb
  )

  $returnMD5 = [string]::Empty
  [int]$chunkSize = $ChunkSizeInMb * [Math]::Pow(2, 20)

  $crypto = New-Object System.Security.Cryptography.MD5CryptoServiceProvider
  [int]$hashLength = $crypto.HashSize / 8

  $stream = [System.IO.File]::OpenRead($Path)

  if($stream.Length -gt $chunkSize) {
    $chunkCount = [int][Math]::Ceiling([double]$stream.Length / [double]$chunkSize)
    [byte[]]$hash = New-Object byte[]($chunkCount * $hashLength)
    $hashStream = New-Object System.IO.MemoryStream(,$hash)
    [long]$numBytesLeftToRead = $stream.Length
    while($numBytesLeftToRead -gt 0) {
      $numBytesCurrentRead = [int][Math]::Min($numBytesLeftToRead, $chunkSize)
      $buffer = New-Object byte[] $numBytesCurrentRead
      $numBytesLeftToRead -= $stream.Read($buffer, 0, $numBytesCurrentRead)
      $tmpHash = $crypto.ComputeHash($buffer)
      $hashStream.Write($tmpHash, 0, $hashLength)
    }
    $returnMD5 = [System.BitConverter]::ToString($crypto.ComputeHash($hash)).Replace("-", "").ToLower() + "-" + $chunkCount
  }
  else {
    $returnMD5 = [System.BitConverter]::ToString($crypto.ComputeHash($stream)).Replace("-", "").ToLower()
  }

  $stream.Close()  
  $returnMD5
}
0
Andrew Marwood