View a markdown version of this page

Cálculos de assinatura para o cabeçalho de autorização: transferência de carga útil em vários fragmentos (upload fragmentado) (AWS Signature Version 4) - Amazon Simple Storage Service

Cálculos de assinatura para o cabeçalho de autorização: transferência de carga útil em vários fragmentos (upload fragmentado) (AWS Signature Version 4)

Conforme descrito na Visão geral, ao autenticar solicitações usando o cabeçalho Authorization, você tem a opção de fazer upload da carga útil em fragmentos. Você pode enviar dados em fragmentos de tamanho fixo ou variável. Esta seção descreve o processo de cálculo da assinatura no upload fragmentado, como você cria o corpo do fragmento e como a assinatura atrasada funciona quando você faz upload do fragmento pela primeira vez e envia a assinatura no fragmento subsequente. A seção de exemplo (consulte Exemplo: objeto PUT) mostra cálculos de assinatura e cabeçalhos Authorization resultantes que você pode usar como um conjunto de testes para verificar seu código.

nota

Ao transferir dados em uma série de fragmentos, você deve fazer o seguinte:

  • Especifique explicitamente o tamanho total do conteúdo (tamanho do objeto em bytes mais metadados em cada parte) usando o cabeçalho HTTP Content-Length. Para fazer isso, você deve pré-calcular o tamanho total da carga útil, incluindo os metadados enviados em cada parte, antes de iniciar sua solicitação.

  • Especifique o cabeçalho HTTP Transfer-Encoding. Se você incluir o cabeçalho Transfer-Encoding e especificar qualquer valor diferente de identity, deverá omitir o cabeçalho Content-Length.

Para todas as solicitações, você deve incluir o cabeçalho x-amz-decoded-content-length, especificando o tamanho do objeto em bytes.

Cada cálculo de assinatura de fragmento inclui a assinatura do fragmento anterior. Para começar, você cria uma assinatura inicial usando somente os cabeçalhos. Você usa a assinatura inicial no cálculo da assinatura do primeiro fragmento. Para cada fragmento subsequente, você cria uma assinatura que inclui a assinatura do fragmento anterior. Assim, as assinaturas de fragmento são encadeadas; ou seja, a assinatura do fragmento n é uma função F(fragmento n, assinatura(fragmento n-1)). O encadeamento garante que você envie os fragmentos na ordem correta.

Para realizar um upload fragmentado, realize estas etapas:

  1. Decida o tamanho do fragmento de carga útil. Você precisa disso ao gravar o código.

    O tamanho do fragmento deve ser de pelo menos 8 KB. Recomendamos um tamanho de fragmento de pelo menos 64 KB para melhor desempenho. Esse tamanho de fragmento se aplica a todos os fragmentos, exceto o último. O último fragmento enviado pode ter menos de 8 KB. Se a carga útil for pequena e couber em um fragmento, ela poderá ser menor que 8 KB.

  2. Crie a assinatura inicial para inclusão no primeiro fragmento. Para obter mais informações, consulte Cálculo da assinatura inicial.

  3. Crie o primeiro fragmento e o transmita. Para obter mais informações, consulte Definição do corpo do fragmento.

  4. Para cada fragmento subsequente, calcule a assinatura que inclui a assinatura anterior na string que você assina, construa o fragmento e o envie. Para obter mais informações, consulte Definição do corpo do fragmento.

  5. Envie o fragmento adicional final, que é igual aos outros fragmentos na construção, mas tem zero bytes de dados. Para obter mais informações, consulte Definição do corpo do fragmento.

Cálculo da assinatura inicial

O diagrama a seguir ilustra o processo de cálculo da assinatura inicial.

O processo de cálculo da assinatura inicial.

A tabela a seguir descreve as funções exibidas no diagrama. É necessário implementar o código para essas funções.

Função Descrição
Lowercase() Converta a string em letras minúsculas.
Hex() Codificação de base 16 em letras minúsculas.
SHA256Hash() Função de hash criptográfico do Secure Hash Algorithm (SHA).
HMAC-SHA256() Calcula o HMAC usando o algoritmo SHA256 com a chave de assinatura fornecida. Essa é a assinatura final.
Trim() Remova qualquer espaço em branco inicial e final.
UriEncode()

O URI codifica cada byte. O UriEncode() deve aplicar as seguintes regras:

  • O URI codifica cada byte, exceto os caracteres não reservados: “A”-“Z”, “a”-“z”, “0”-“9”, “-”, “.”, “_” e “~”.

  • O caractere de espaço é um caractere reservado e deve ser codificado como “%20” (e não como “+”).

  • Cada byte codificado por URI é formado por um “%” e o valor hexadecimal de dois dígitos do byte.

  • As letras no valor hexadecimal devem estar em maiúsculas; por exemplo, “%1A”.

  • Codifique o caractere de barra, “/”, em todos os lugares, exceto no nome da chave do objeto. Por exemplo, se o nome da chave do objeto for photos/Jan/sample.jpg, a barra no nome da chave não está codificada.

Importante

As funções UriEncode padrão fornecidas por sua plataforma de desenvolvimento podem não funcionar devido às diferenças na implementação e à ambiguidade relacionada nos RFCs subjacentes. É recomendável escrever sua própria função UriEncode personalizada para garantir que a codificação funcione.

Veja a seguir um exemplo da função UriEncode() em Java.

public static String UriEncode(CharSequence input, boolean encodeSlash) { StringBuilder result = new StringBuilder(); for (int i = 0; i < input.length(); i++) { char ch = input.charAt(i); if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '-' || ch == '~' || ch == '.') { result.append(ch); } else if (ch == '/') { result.append(encodeSlash ? "%2F" : ch); } else { result.append(toHexUTF8(ch)); } } return result.toString(); }

Para obter informações sobre o processo de assinatura, consulte Cálculos de assinatura para o cabeçalho de autorização: transferência de carga útil em uma única parte (AWS Signature Version 4). O processo é o mesmo, mas a criação de CanonicalRequest difere da seguinte forma:

  • Além dos cabeçalhos de solicitação que pretende adicionar, você deve incluir os seguintes cabeçalhos:

    Cabeçalho Descrição
    x-amz-content-sha256

    Esse cabeçalho é obrigatório para todas as solicitações do AWS Signature Version 4. Defina o valor como STREAMING-AWS4-HMAC-SHA256-PAYLOAD para indicar que a assinatura cobre somente cabeçalhos e que não há carga útil.

    Content-Encoding

    Defina o valor como aws-chunked.

    O Amazon S3 oferece suporte a vários valores de codificação de conteúdo. Você pode especificar a codificação de conteúdo personalizada ao usar a API de streaming do Signature Version 4.

    Por exemplo:

    Content-Encoding : aws-chunked,gzip

    O Amazon S3 armazena o objeto resultante sem o valor aws-chunked no cabeçalho content-encoding. Se aws-chunked for o único valor transmitido no cabeçalho content-encoding, o S3 vai considerar o cabeçalho content-encoding vazio e não vai retornar esse cabeçalho quando você recuperar o objeto.

    x-amz-decoded-content-length Defina o valor como o tamanho, em bytes, dos dados a serem fragmentados, sem contar nenhum metadado. Por exemplo, se você estiver carregando um arquivo de 4 GB, defina o valor como 4294967296. Esse é o tamanho bruto do objeto a ser carregado (dados que você deseja armazenar no Amazon S3).
    Content-Length

    Defina o valor como o tamanho real do corpo HTTP transmitido, que inclui o tamanho dos seus dados (valor definido para x-amz-decoded-content-length), além dos metadados de fragmento. Cada fragmento tem metadados, como a assinatura do fragmento anterior. Os cálculos de fragmentos serão discutidos na seção a seguir. Se você incluir o cabeçalho Transfer-Encoding e especificar qualquer valor diferente de identity, não inclua o cabeçalho Content-Length.

Envie o primeiro fragmento com a assinatura inicial. Você deve construir o fragmento conforme descrito na seção a seguir.

Definição do corpo do fragmento

Todos os fragmentos incluem alguns metadados. Cada fragmento deve estar de acordo com a seguinte estrutura:

string(IntHexBase(chunk-size)) + ";chunk-signature=" + signature + \r\n + chunk-data + \r\n

Em que:

  • IntHexBase() é uma função gravada para converter um tamanho de fragmento inteiro em hexadecimal. Por exemplo, se o tamanho do fragmento for 65536, a string hexadecimal será “10000”.

  • chunk-size é o tamanho, em bytes, dos dados do fragmento, sem metadados. Por exemplo, se estiver carregando um objeto de 65 KB e usando um tamanho de fragmento de 64 KB, você carregará os dados em três fragmentos: o primeiro teria 64 KB, o segundo 1 KB e o fragmento final com 0 bytes.

  • signature Para cada fragmento, você calcula a assinatura usando a seguinte string a ser assinada. Para o primeiro fragmento, você usa a assinatura inicial como a assinatura anterior.

    O processo de cálculo da assinatura inicial mostrando vários componentes da string a ser assinada.

O tamanho dos dados do fragmento final que você envia é 0, embora o corpo do fragmento ainda contenha metadados, incluindo a assinatura do fragmento anterior.

Exemplo: objeto PUT

Você pode usar os exemplos desta seção como uma referência para verificar os cálculos de assinatura no seu código. Antes de analisar os exemplos, observe o seguinte:

  • Os cálculos de assinatura nesses exemplos usam os seguintes exemplos de credenciais de segurança.

    Parâmetro Valor
    AWSAccessKeyId AKIAIOSFODNN7EXAMPLE
    AWSSecretAccessKey wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
  • Todos os exemplos usam o carimbo de data/hora de solicitação 20130524T000000Z (Fri, 24 May 2013 00:00:00 GMT).

  • Todos os exemplos usam examplebucket como nome do bucket.

  • Presume-se que o bucket esteja na região Leste dos EUA (Norte da Virgínia) e a credencial Scope e os cálculos de Signing Key usem us-east-1 como especificador da região. Para obter mais informações, consulte Regiões e endpoints na Referência geral da Amazon Web Services.

  • Você pode usar solicitações no estilo de caminho ou no estilo hospedado virtual. Os exemplos a seguir usam solicitações de estilo hospedado virtual, por exemplo:

    https://examplebucket.s3.amazonaws.com/photos/photo1.jpg

    Para obter mais informações, consulte Hospedagem virtual de buckets no Guia do usuário do Amazon Simple Storage Service.

O exemplo a seguir envia uma solicitação PUT para fazer upload de um objeto. Os cálculos de assinatura presumem o seguinte:

  • Você está fazendo o upload de um arquivo de texto de 65 KB, e o conteúdo do arquivo é uma string de um único caractere composta pela letra ‘a’.

  • O fragmento tem 64 KB. Como resultado, a carga útil é carregada em três fragmentos: 64 KB, 1 KB e o fragmento final com 0 bytes de dados.

  • O objeto resultante tem o nome de chave chunkObject.txt.

  • Você está solicitando REDUCED_REDUNDANCY como classe de armazenamento adicionando o cabeçalho de solicitação x-amz-storage-class.

Para obter informações sobre a ação da API, consulte PutObject. A sintaxe de solicitação geral é a seguinte:

PUT /examplebucket/chunkObject.txt HTTP/1.1 Host: s3.amazonaws.com x-amz-date: 20130524T000000Z x-amz-storage-class: REDUCED_REDUNDANCY Authorization: SignatureToBeCalculated x-amz-content-sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD Content-Encoding: aws-chunked x-amz-decoded-content-length: 66560 Content-Length: 66824 <Payload>

As etapas a seguir mostram cálculos de assinatura.

  1. Assinatura inicial — Criar uma string a ser assinada
    1. CanonicalRequest

      PUT /examplebucket/chunkObject.txt content-encoding:aws-chunked content-length:66824 host:s3.amazonaws.com x-amz-content-sha256:STREAMING-AWS4-HMAC-SHA256-PAYLOAD x-amz-date:20130524T000000Z x-amz-decoded-content-length:66560 x-amz-storage-class:REDUCED_REDUNDANCY content-encoding;content-length;host;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length;x-amz-storage-class STREAMING-AWS4-HMAC-SHA256-PAYLOAD

      Na solicitação canônica, a terceira linha está vazia, pois não há parâmetros de consulta na solicitação. A última linha é a string constante fornecida como o valor da carga útil com hash, que deve ser igual ao valor de x-amz-content-sha256 header.

    2. StringToSign

      AWS4-HMAC-SHA256 20130524T000000Z 20130524/us-east-1/s3/aws4_request cee3fed04b70f867d036f722359b0b1f2f0e5dc0efadbc082b76c4c60e316455

      nota

      Para obter informações sobre cada linha na string a ser assinada, consulte o diagrama que explica o cálculo da assinatura inicial.

  2. SigningKey

    signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("AWS4" + "<YourSecretAccessKey>","20130524"),"us-east-1"),"s3"),"aws4_request")

  3. Assinatura inicial

    4f232c4386841ef735655705268965c44a0e4690baa4adea153f7db9fa80a0a9

  4. Cabeçalho de autorização

    O cabeçalho de autorização resultante é o seguinte:

    AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,SignedHeaders=content-encoding;content-length;host;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length;x-amz-storage-class,Signature=4f232c4386841ef735655705268965c44a0e4690baa4adea153f7db9fa80a0a9

  5. Fragmento 1: (65536 bytes, com valor 97 para a letra ‘a’)
    1. String do fragmento a ser assinada:

      AWS4-HMAC-SHA256-PAYLOAD 20130524T000000Z 20130524/us-east-1/s3/aws4_request 4f232c4386841ef735655705268965c44a0e4690baa4adea153f7db9fa80a0a9 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 bf718b6f653bebc184e1479f1935b8da974d701b893afcf49e701f3e2f9f9c5a

      nota

      Para obter informações sobre cada linha na string a ser assinada, consulte o diagrama anterior que mostra vários componentes da string a ser assinada (por exemplo, as últimas três linhas são previous-signature, hash("") e hash(current-chunk-data)).

    2. Assinatura do fragmento:

      ad80c730a21e5b8d04586a2213dd63b9a0e99e0e2307b0ade35a65485a288648
    3. Dados do fragmento enviados:

      10000;chunk-signature=ad80c730a21e5b8d04586a2213dd63b9a0e99e0e2307b0ade35a65485a288648 <65536-bytes>
  6. Fragmento 2: (1024 bytes, com valor 97 para a letra ‘a’)
    1. String do fragmento a ser assinada:

      AWS4-HMAC-SHA256-PAYLOAD 20130524T000000Z 20130524/us-east-1/s3/aws4_request ad80c730a21e5b8d04586a2213dd63b9a0e99e0e2307b0ade35a65485a288648 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 2edc986847e209b4016e141a6dc8716d3207350f416969382d431539bf292e4a
    2. Assinatura do fragmento:

      0055627c9e194cb4542bae2aa5492e3c1575bbb81b612b7d234b86a503ef5497
    3. Dados do fragmento enviados:

      400;chunk-signature=0055627c9e194cb4542bae2aa5492e3c1575bbb81b612b7d234b86a503ef5497 <1024 bytes>
  7. Fragmento 3: (0 bytes de dados)
    1. String do fragmento a ser assinada:

      AWS4-HMAC-SHA256-PAYLOAD 20130524T000000Z 20130524/us-east-1/s3/aws4_request 0055627c9e194cb4542bae2aa5492e3c1575bbb81b612b7d234b86a503ef5497 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    2. Assinatura do fragmento:

      b6c6ea8a5354eaf15b3cb7646744f4275b71ea724fed81ceb9323e279d449df9
    3. Dados do fragmento enviados:

      0;chunk-signature=b6c6ea8a5354eaf15b3cb7646744f4275b71ea724fed81ceb9323e279d449df9