Assinaturas

As assinaturas são um método de autenticação de pedidos enviados para a API XML do Cloud Storage. As assinaturas são usadas, por exemplo, quando trabalha com URLs assinados ou formulários HTML. Esta página aplica-se a assinaturas criadas através do processo de assinatura V4, que é o processo recomendado para criar assinaturas.

As assinaturas são específicas da API XML do Cloud Storage e são distintas dos tokens do OAuth 2.0. Os tokens do OAuth 2.0 também podem ser usados com a API XML e são mais geralmente aplicáveis nos serviços Google Cloud , incluindo a API JSON do Cloud Storage.

Vista geral

As assinaturas fornecem identidade e autenticação forte, o que garante que os pedidos ao Cloud Storage são processados com a autoridade de uma conta específica. As assinaturas alcançam essa autenticação sem revelar as informações confidenciais da chave, denominadas segredos ou chaves privadas, associadas a essa conta.

Quando faz um pedido com uma assinatura, o Cloud Storage usa a respetiva cópia das informações da chave para calcular uma assinatura equivalente para o pedido. Se a assinatura incluída no pedido corresponder à assinatura calculada pelo Cloud Storage, o Cloud Storage sabe que a assinatura foi criada com a chave secreta ou privada relevante.

No Cloud Storage, as assinaturas têm de ser usadas quando trabalha com:

Além disso, as assinaturas podem ser usadas no cabeçalho Authorization de pedidos da API XML.

A utilização de assinaturas em pedidos diretos é útil quando se realizam migrações simples do Amazon S3. No entanto, o fluxo de autenticação recomendado para pedidos diretos é a utilização de tokens OAuth 2.0.

Estrutura

Os componentes e o processo de criação de uma assinatura dependem da finalidade e da chave de autenticação com que está a trabalhar. Em geral, existem dois componentes numa assinatura: a chave de assinatura e as informações do pedido. Aplica um algoritmo de assinatura a estes dois componentes para criar a assinatura. A tabela abaixo resume os diferentes exemplos de utilização das assinaturas e os componentes de que precisa em cada caso para criar a assinatura:

Exemplo de utilização Chave de assinatura Peça informações
Formulário HTML com uma chave RSA Usar diretamente a chave privada RSA Documento de política codificado em Base64
Formulário HTML com uma chave HMAC Derive do segredo da chave HMAC Documento de política codificado em Base64
URL assinado ou cabeçalho assinado com uma chave RSA Usar diretamente a chave privada RSA String-to-sign
URL assinado ou cabeçalho assinado com uma chave HMAC Derive do segredo da chave HMAC String-to-sign

String para sinal

Uma string-to-sign inclui metainformações sobre o seu pedido e um hash do pedido canónico que quer assinar.

Estrutura

Uma string para assinar tem de estar codificada em UTF-8 e tem a seguinte estrutura, incluindo a utilização de novas linhas entre cada elemento:

SIGNING_ALGORITHM
ACTIVE_DATETIME
CREDENTIAL_SCOPE
HASHED_CANONICAL_REQUEST

Algoritmo de assinatura

O valor que usa para SIGNING_ALGORITHM depende do tipo de chave que usa e das extensões que usa para os seus cabeçalhos ou parâmetros de consulta:

Exemplo de utilização Valor para SIGNING_ALGORITHM
x-goog-* extensões e uma chave RSA GOOG4-RSA-SHA256
x-goog-* extensões e uma chave HMAC GOOG4-HMAC-SHA256
x-amz-* extensões e uma chave HMAC AWS4-HMAC-SHA256

Data/hora de atividade

A data e a hora em que a assinatura pode ser usada, no formato básico YYYYMMDD'T'HHMMSS'Z' da norma ISO 8601.

  • Para URLs assinados, a assinatura é utilizável 15 minutos antes da data/hora ativa até à hora de validade especificada. A data/hora ativa tem de corresponder ao parâmetro de string de consulta X-Goog-Date do URL assinado e tem de usar o mesmo dia que especificar no âmbito das credenciais.

  • Para pedidos com cabeçalhos assinados, a assinatura é utilizável 15 minutos antes da data/hora ativa até 15 minutos após a data/hora ativa. A data/hora ativa tem de corresponder ao cabeçalho x-goog-date do pedido através da assinatura e tem de usar o mesmo dia que especificar no âmbito das credenciais.

Âmbito das credenciais

O âmbito da credencial para o pedido.

Hash do pedido canónico

O hash SHA-256 codificado no formato hexadecimal de um pedido canónico. Use uma função de aplicação de hash SHA-256 para criar um valor de hash do pedido canónico. A sua linguagem de programação deve ter uma biblioteca para criar hashes SHA-256. Um exemplo de um valor hash tem o seguinte aspeto:

436b7ce722d03b17d3f790255dd57904f7ed61c02ac5127a0ca8063877e4e42c

Exemplo

Segue-se um exemplo de uma string para assinatura formada corretamente, com novas linhas apresentadas como novas linhas reais e não \n:

GOOG4-RSA-SHA256
20191201T190859Z
20191201/us-central1/storage/goog4_request
54f3076005db23fbecdb409d25c0ccb9fb8b5e24c59f12634654c0be13459af0

Documento de política

Um documento de política define o que os utilizadores com acesso ao formulário HTML correspondente podem carregar para o Cloud Storage. Um documento de política fornece autorização para garantir que o formulário HTML pode carregar ficheiros para o contentor de destino. Pode usar documentos de políticas para permitir que os visitantes de um Website carreguem ficheiros para o Cloud Storage.

Um documento de política é construído em JavaScript Object Notation (JSON). O documento de política tem de estar codificado em UTF-8 e Base64. Um documento de política contém as seguintes secções:

Entrada Descrição
expiration A hora de validade do documento de política, no formato básico ISO 8601 YYYYMMDD'T'HHMMSS'Z'. Um documento de política expirado faz com que o formulário HTML deixe de funcionar.
conditions Uma matriz de condições que todos os carregamentos têm de satisfazer.

A secção conditions tem de incluir:

  • Uma declaração de condição para cada campo que usa no seu formulário HTML, exceto para os campos x-goog-signature, file e policy.

  • Uma declaração de "bucket" condição, mesmo que não use o campo de contentor no seu formulário HTML.

Se quiser usar várias declarações de condições para o mesmo campo, deve criar um formulário HTML separado para cada uma. Podem ser usados três tipos de condições nas suas declarações de condições:

  • Correspondência exata

    Faz a correspondência exata de um campo. O valor usado no campo especificado do formulário HTML tem de corresponder ao valor definido nesta condição. Defina esta condição com um dos seguintes estilos de sintaxe:

    {"field" : "value"}
    ["eq", "$field", "value"]

    Todos os campos de formulários HTML válidos, exceto Content-Length, podem usar a correspondência exata.

  • Começa com

    Se o valor de um campo tiver de começar por um determinado prefixo, use a condição starts-with com a seguinte sintaxe:

    ["starts-with", "$field", "value"]

    Se o valor de um campo não tiver restrições, use a condição starts-with com a seguinte sintaxe:

    ["starts-with", "$field", ""]

    Todos os campos de formulário HTML válidos, exceto Content-Length, podem usar a condição starts-with.

  • Intervalo de duração do conteúdo

    Especifica um intervalo de valores aceitáveis que podem ser usados no campo Content-Length. Especifique esta condição através da seguinte sintaxe:

    ["content-length-range", min_range, max_range]

Exemplo

Segue-se um exemplo de um documento de política:

{"expiration": "2020-06-16T11:11:11Z",
 "conditions": [
  ["starts-with", "$key", ""],
  {"bucket": "travel-maps"},
  {"success_action_redirect": "http://www.example.com/success_notification.html"},
  ["eq", "$Content-Type", "image/jpeg"],
  ["content-length-range", 0, 1000000],
  {"x-goog-algorithm": "GOOG4-RSA-SHA256"},
  {"x-goog-credential": "example_account@example_project.iam.gserviceaccount.com/20191102/us-central1/storage/goog4_request"},
  {"x-goog-date": "20191102T043530Z"}
  ]
}

Este documento de política define as seguintes condições:

  • O formulário expira a 16 de junho de 2020 às 11:11:11 UTC.
  • O nome do ficheiro pode começar com qualquer caráter válido.
  • O ficheiro tem de ser carregado para o contentor travel-maps.
  • Se o carregamento for bem-sucedido, o utilizador é redirecionado para http://www.example.com/success_notification.html.
  • O formulário só permite o carregamento de imagens.
  • Um utilizador não pode carregar um ficheiro com mais de 1 MB.

Âmbito das credenciais

O âmbito das credenciais é uma string que aparece nos documentos de string para sinais e de políticas. O âmbito das credenciais tem a seguinte estrutura:

DATE/LOCATION/SERVICE/REQUEST_TYPE

O âmbito das credenciais tem os seguintes componentes:

  • DATE: a data em que a assinatura fica utilizável, formatada como AAAAMMDD.
  • LOCATION: para recursos do Cloud Storage, pode usar qualquer valor para LOCATION. O valor recomendado a usar é a localização associada ao recurso ao qual a assinatura se aplica. Por exemplo, us-central1. Este parâmetro existe para manter a compatibilidade com o Amazon S3.
  • SERVICE: o nome do serviço. Na maioria dos casos, quando acede a recursos do Cloud Storage, este valor é storage. Quando usar extensões do Amazon S3 x-amz, este valor é s3.
  • REQUEST_TYPE: o tipo de pedido. Na maioria dos casos, quando acede a recursos do Cloud Storage, este valor é goog4_request. Quando usar extensões do Amazon S3 x-amz, este valor é aws4_request.

Por exemplo, um âmbito de credenciais típico tem o seguinte aspeto:

20191102/us-central1/storage/goog4_request

Embora um âmbito das credenciais quando usa uma string para assinar com extensões x-amz seja semelhante a:

20150830/us-east1/s3/aws4_request

Assinatura

Para criar uma assinatura, usa um algoritmo de assinatura, também conhecido como uma função de hash criptográfica, para assinar a sua string a assinar ou documento de política. O algoritmo de assinatura produz um resumo da mensagem, que tem de ser codificado em hexadecimal para criar a assinatura final. O algoritmo de assinatura que usa depende do tipo de chave de autenticação que tem:

Chave de autenticação Algoritmo de assinatura Chave de assinatura
Chave RSA RSA-SHA256 Usar diretamente a chave privada RSA
Chave HMAC HMAC-SHA256 Derive do segredo da chave HMAC

O algoritmo de assinatura RSA-SHA256 pode ser executado através do método IAM signBlob. As ferramentas, como a CLI gcloud e a maioria das Google Cloud bibliotecas de cliente, permitem-lhe criar URLs assinados através do método signBlob.

Também pode criar assinaturas de chaves RSA localmente através de uma linguagem de programação que tenha uma biblioteca para executar assinaturas RSA, como a biblioteca pyopenssl. No entanto, este método é desaconselhado, uma vez que requer que crie e transfira a chave privada de uma conta de serviço.

Derive a chave de assinatura da chave HMAC

Quando assina com uma chave HMAC, tem de criar uma chave de assinatura codificada em UTF-8 que seja derivada do segredo da chave HMAC. A chave derivada é específica da data, da localização, do serviço e do tipo de pedido associados ao seu pedido. O pseudocódigo seguinte mostra como derivar a chave de assinatura:

key_date = HMAC-SHA256("PREFIX" + HMAC_KEY_SECRET, "DATE")
key_region = HMAC-SHA256(key_date, "LOCATION")
key_service = HMAC-SHA256(key_region, "SERVICE")
signing_key = HMAC-SHA256(key_service, "REQUEST_TYPE")

O pseudocódigo tem os seguintes componentes:

  • PREFIX: na maioria dos casos, quando acede a recursos do Cloud Storage, este valor é GOOG4. Quando usar extensões do Amazon S3, este valor é AWS4.x-amz
  • HMAC_KEY_SECRET: o segredo da chave HMAC que está a usar para criar e assinar o pedido.
  • DATE, LOCATION, SERVICE, REQUEST_TYPE: estes valores têm de corresponder aos valores especificados no âmbito das credenciais.

Depois de derivar a chave de assinatura, cria a assinatura localmente através de uma linguagem de programação que inclua uma biblioteca com o algoritmo de assinatura HMAC-SHA256.

Após a assinatura

Para concluir a assinatura, o resultado da assinatura, denominado message digest, tem de ser codificado em hexadecimal.

Exemplo

Segue-se um pseudocódigo para assinar um documento de política:

EncodedPolicy = Base64Encode(PolicyDocument)
MessageDigest = SigningAlgorithm(SigningKey, EncodedPolicy)
Signature = HexEncode(MessageDigest)

Segue-se o pseudocódigo para assinar uma string a assinar:

MessageDigest = SigningAlgorithm(SigningKey, StringToSign)
Signature = HexEncode(MessageDigest)

O que se segue?