Подтвердить что ты не робот

Как получить файл md5sum на Amazon S3

Если у меня есть существующие файлы на Amazon S3, какой самый простой способ получить их md5sum без необходимости скачивать файлы?

Спасибо

4b9b3361

Ответ 1

Хмм... Я думаю, вы можете посмотреть заголовок ETag. (в этом случае вы можете использовать HTTP HEAD, а не GET.) Они не совсем говорят это явно, но это почти наверняка Amazon использует MD5 хэш для ETag. Из Документация PUT Object (не знаю почему они не просто выходят и говорят это):

Чтобы данные не были повреждены по сети, используйте заголовок Content-MD5. Когда вы используете заголовок Content-MD5, Amazon S3 проверяет объект на предоставленное MD5 значение. Если они не совпадают, Amazon S3 возвращает ошибку. Кроме того, вы можете вычислить MD5, поместив объект в Amazon S3 и сравните возвращаемый Etag с вычисленным значением MD5.

Кроме того, методы

Ответ 2

ETag, похоже, не MD5 для многостраничных загрузок (согласно комментарию Gael Fraiteur). В этих случаях он содержит суффикс минуса и числа. Однако даже бит до минуса не кажется MD5, хотя он имеет ту же длину, что и MD5. Возможно, суффикс - это количество загруженных частей?

Ответ 3

Документация AWS ETag гласит:

Тег объекта - это хэш объекта. ETag отражает изменения только для содержимого объекта, а не его метаданных. ETag может быть или не быть дайджестом MD5 данных объекта. Независимо от того, зависит оно от того, как был создан объект и как он зашифрован, как описано ниже:

  • Объекты, созданные объектом PUT Object, POST Object или Copy, или через консоль управления AWS и зашифрованные SSE-S3 или открытым текстом, имеют ETags, которые являются дайджестом MD5 их данных объекта.
  • Объекты, созданные объектом PUT Object, POST Object или Copy или через AWS Management Console и зашифрованные SSE-C или SSE-KMS, имеют ETags, которые не являются дайджестом MD5 их данных объекта.
  • Если объект создается с помощью операции Multipart Upload или Part Copy, ETag не является дайджестом MD5, независимо от метода шифрования.

Ссылка: http://docs.aws.amazon.com/AmazonS3/latest/API/RESTCommonResponseHeaders.html

Ответ 4

Для тех, кто тратит время на поиск, чтобы узнать, почему md5 не совпадает с ETag в S3.

ETag будет вычислять с помощью патча данных и concat all md5hash, чтобы снова сделать хеш md5 и сохранить количество фрагментов в конце.

Вот версия С# для генерации хэша

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

исходный код

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

Ответ 5

Я обнаружил, что у s3cmd есть опция --list-md5, которую можно использовать с командой ls, например,

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

Надеюсь, это поможет.

Ответ 6

У меня есть cross checked jets3t и консоль управления от MD5sum загруженных файлов, а ETag похоже на MD5sum. Вы можете просто просмотреть свойства файла в консоли управления AWS:

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

Ответ 7

Самый простой способ - установить контрольную сумму в качестве метаданных, прежде чем загружать эти файлы в корзину:

ObjectMetadata md = new ObjectMetadata();
md.setContentMD5("foobar");
PutObjectRequest req = new PutObjectRequest(BUCKET, KEY, new File("/path/to/file")).withMetadata(md);
tm.upload(req).waitForUploadResult();

Теперь вы можете получить доступ к этим метаданным, не загружая файл:

ObjectMetadata md2 = s3Client.getObjectMetadata(BUCKET, KEY);
System.out.println(md.getContentMD5());

источник: https://github.com/aws/aws-sdk-java/issues/1711

Ответ 8

Ниже этой работы для меня, чтобы сравнить локальную контрольную сумму файла с s3 etag. Я использовал Python

def md5_checksum(filename):
    m = hashlib.md5()
    with open(filename, 'rb') as f:
        for data in iter(lambda: f.read(1024 * 1024), b''):
            m.update(data)
   
    return m.hexdigest()


def etag_checksum(filename, chunk_size=8 * 1024 * 1024):
    md5s = []
    with open(filename, 'rb') as f:
        for data in iter(lambda: f.read(chunk_size), b''):
            md5s.append(hashlib.md5(data).digest())
    m = hashlib.md5(b"".join(md5s))
    print('{}-{}'.format(m.hexdigest(), len(md5s)))
    return '{}-{}'.format(m.hexdigest(), len(md5s))

def etag_compare(filename, etag):
    et = etag[1:-1] # strip quotes
    print('et',et)
    if '-' in et and et == etag_checksum(filename):
        return True
    if '-' not in et and et == md5_checksum(filename):
        return True
    return False


def main():   
    session = boto3.Session(
        aws_access_key_id=s3_accesskey,
        aws_secret_access_key=s3_secret
    )
    s3 = session.client('s3')
    obj_dict = s3.get_object(Bucket=bucket_name, Key=your_key)

    etag = (obj_dict['ETag'])
    print('etag', etag)
    
    validation = etag_compare(filename,etag)
    print(validation)
    etag_checksum(filename, chunk_size=8 * 1024 * 1024)
    return validation

Ответ 9

Это работает для меня. В PHP вы можете сравнить контрольную сумму между локальным файлом e amazon, используя это:



    // 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;
        }
    }

Ответ 10

Здесь код для получения S3 ETag для объекта в PowerShell, преобразованный из С#.

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
}

Ответ 11

Вот код, чтобы получить хеш MD5 в соответствии с 2017

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Base64;
public class GenerateMD5 {
public static void main(String args[]) throws Exception{
    String s = "<CORSConfiguration> <CORSRule> <AllowedOrigin>http://www.example.com</AllowedOrigin> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>POST</AllowedMethod> <AllowedMethod>DELETE</AllowedMethod> <AllowedHeader>*</AllowedHeader> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <AllowedHeader>*</AllowedHeader> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> </CORSConfiguration>";

        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(s.getBytes());
        byte[] digest = md.digest();
        StringBuffer sb = new StringBuffer();
        /*for (byte b : digest) {
            sb.append(String.format("%02x", b & 0xff));
        }*/
        System.out.println(sb.toString());
        StringBuffer sbi = new StringBuffer();
        byte [] bytes = Base64.encodeBase64(digest);
        String finalString = new String(bytes);
        System.out.println(finalString);
    }
}

Прокомментированный код - это то, где большинство людей ошибочно меняют его на hex