Usar uma assinatura digital

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Assinar digitalmente sua solicitação com uma chave de API

Dependendo do uso, uma assinatura digital, além de uma chave de API, pode ser necessária para autenticar solicitações. Consulte Outros limites de uso.

Como funcionam as assinaturas digitais

As assinaturas digitais são geradas usando uma Chave secreta de assinatura do URL, disponível no Console do Google Cloud. Ela é essencialmente uma chave privada, compartilhada somente entre você e o Google, e pertence exclusivamente ao seu projeto.

O processo de assinatura usa um algoritmo de criptografia para combinar o URL e a chave secreta compartilhada. A assinatura exclusiva resultante permite que nossos servidores verifiquem se qualquer site que gera solicitações usando sua chave de API está autorizado a fazer isso.

Limitar solicitações não assinadas

Para garantir que a chave de API aceite apenas solicitações assinadas, faça o seguinte:

  1. Acesse a página Cotas da Plataforma Google Maps no Console do Cloud.
  2. Clique na lista suspensa e selecione o mesmo projeto que você usou ao criar a chave de API para a API Street View Static.
  3. Selecione o menu suspenso de APIs e escolha API Street View Static.
  4. Expanda a seção Solicitações não assinadas.
  5. Na tabela Nome da cota, clique no botão de edição ao lado da cota que você quer editar. Por exemplo, Solicitações não assinadas por dia.
  6. Atualize o Limite de cota no painel Editar limite de cota.
  7. Selecione Salvar.

Assinar suas solicitações

Veja a seguir as etapas para assinar suas solicitações:

Etapa 1: gerar a Chave secreta de assinatura do URL

Para ver a Chave secreta de assinatura do URL do projeto, siga estas etapas:

  1. Acesse a página Credenciais da Plataforma Google Maps no Console do Cloud.
  2. Selecione o menu suspenso do projeto e escolha o mesmo projeto que você usou quando criou a chave de API para a API Street View Static.
  3. Selecione o menu suspenso de APIs e escolha API Street View Static.
  4. Role para baixo até o card Gerador de secrets. No campo Chave secreta atual, está a Chave secreta de assinatura do URL atual.
  5. A página também apresenta o widget Assinar URL agora, que permite a assinatura automática de uma solicitação da API Street View Static usando a Chave secreta de assinatura atual. Role para baixo até o card Assinar URL agora para acessá-lo.

Para gerar um nova chave secreta de assinatura do URL, selecione Gerar chave secreta novamente. A chave anterior expira 24 horas após a criação de uma nova chave secreta. Após 24 horas, as solicitações que contiverem o segredo antigo deixarão de funcionar.

Etapa 2: criar solicitação sem assinatura

Os caracteres não listados na tabela abaixo precisam ser codificados para uso em URL:

Resumo de caracteres válidos para URLs
ConjuntoCaracteresUso em URLs
Alfanuméricos a b c d e f g h i j k k l m n o p q r s t u v x y z A B C D E F G H I J K L M N N P P R S T U V X Y Z 0 1 2 3 4 5 5 5 Strings de texto, uso do esquema (http), porta (8080) etc.
Não reservados - _ . ~ Strings de texto
Reservados ! * ' ( ) ; : @ & = + $ , / ? % # [ ] Caracteres de controle e/ou strings de texto

O mesmo se aplica a todos os caracteres no conjunto Reservado, se eles forem transferidos dentro de uma string de texto. Para mais informações, consulte Caracteres especiais.

Gere o URL de solicitação sem assinatura. Para ver instruções, consulte o guia do desenvolvedor da API Street View Static.

Inclua também a chave de API no parâmetro key. Exemplo:

https://maps.googleapis.com/maps/api/streetview?location=41.403609,2.174448&size=456x456&key=YOUR_API_KEY

Gerar a solicitação assinada

Para casos de uso únicos, como hospedar uma imagem simples da API Maps Static ou da API Street View Static na sua página da Web ou para fins de solução de problemas, você pode gerar uma assinatura digital automaticamente usando o widget Assinar URL agora.

Para solicitações geradas dinamicamente, você precisa da assinatura do lado do servidor, que requer mais algumas etapas intermediárias.

De qualquer forma, haverá um URL de solicitação com um parâmetro signature anexado ao final. Exemplo:

https://maps.googleapis.com/maps/api/streetview?location=41.403609,2.174448&size=456x456&key=YOUR_API_KEY
&signature=BASE64_SIGNATURE
Usar o widget Assinar URL agora

Para gerar uma assinatura digital com uma chave de API usando o widget Assinar URL agora no Console do Google Cloud:

  1. Localize o widget Assinar URL agora, conforme descrito na Etapa 1: gerar a Chave secreta de assinatura do URL.
  2. No campo URL, cole o URL da Etapa 2: criar solicitação sem assinatura.
  3. O URL assinado digitalmente aparecerá no campo Seu URL assinado. Lembre-se de fazer uma cópia dele.
Gerar assinaturas digitais do lado do servidor

Além das etapas do widget Assinar URL agora, você precisará realizar algumas outras ações ao gerar assinaturas digitais do lado do servidor:

  1. Remova o esquema do protocolo e as partes do host do URL, deixando apenas o caminho e a consulta:

  2. /maps/api/streetview?location=41.403609,2.174448&size=456x456&key=YOUR_API_KEY
    
  3. A Chave secreta de assinatura do URL exibida é codificada em um Base64 modificado para URLs.

    Como a maioria das bibliotecas criptográficas exige que a chave esteja no formato de bytes brutos, você provavelmente precisará decodificar a Chave secreta de assinatura do URL no formato bruto original antes de assinar.

  4. Assine a solicitação com as partes removidas acima usando HMAC-SHA1.
  5. Como a maioria das bibliotecas criptográficas gera uma assinatura no formato de byte bruto, você precisará acessar a assinatura binária resultante usando o método Base64 modificado para que os URLs o convertam em algo que possa ser transmitido dentro do URL.

  6. Anexe a assinatura codificada com Base64 ao URL original da solicitação não assinada no parâmetro signature. Exemplo:

    https://maps.googleapis.com/maps/api/streetview?location=41.403609,2.174448&size=456x456&key=YOUR_API_KEY
    &signature=BASE64_SIGNATURE

Para ver exemplos de como implementar a assinatura de URL usando o código do lado do servidor, consulte abaixo o Exemplo de código para assinatura de URL.

Exemplo de código para assinatura de URL

As seções a seguir mostram como implementar a assinatura de URL usando o código do lado do servidor. Os URLs precisam sempre ser assinados no servidor para evitar a exposição da Chave secreta de assinatura do URL aos usuários.

Python

O exemplo abaixo usa bibliotecas Python padrão para assinar um URL. Faça o download do código (link em inglês).

#!/usr/bin/python
# -*- coding: utf-8 -*-
""" Signs a URL using a URL signing secret """

import hashlib
import hmac
import base64
import urllib.parse as urlparse


def sign_url(input_url=None, secret=None):
    """ Sign a request URL with a URL signing secret.
      Usage:
      from urlsigner import sign_url
      signed_url = sign_url(input_url=my_url, secret=SECRET)
      Args:
      input_url - The URL to sign
      secret    - Your URL signing secret
      Returns:
      The signed request URL
  """

    if not input_url or not secret:
        raise Exception("Both input_url and secret are required")

    url = urlparse.urlparse(input_url)

    # We only need to sign the path+query part of the string
    url_to_sign = url.path + "?" + url.query

    # Decode the private key into its binary format
    # We need to decode the URL-encoded private key
    decoded_key = base64.urlsafe_b64decode(secret)

    # Create a signature using the private key and the URL-encoded
    # string using HMAC SHA1. This signature will be binary.
    signature = hmac.new(decoded_key, str.encode(url_to_sign), hashlib.sha1)

    # Encode the binary signature into base64 for use within a URL
    encoded_signature = base64.urlsafe_b64encode(signature.digest())

    original_url = url.scheme + "://" + url.netloc + url.path + "?" + url.query

    # Return signed URL
    return original_url + "&signature=" + encoded_signature.decode()


if __name__ == "__main__":
    input_url = input("URL to Sign: ")
    secret = input("URL signing secret: ")
    print("Signed URL: " + sign_url(input_url, secret))

Java

O exemplo abaixo usa a classe java.util.Base64 disponível desde o JDK 1.8. Talvez as versões mais antigas precisem usar o Apache Commons ou similar. Faça o download do código (link em inglês).

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;  // JDK 1.8 only - older versions may need to use Apache Commons or similar.
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class UrlSigner {

  // Note: Generally, you should store your private key someplace safe
  // and read them into your code

  private static String keyString = "YOUR_PRIVATE_KEY";
  
  // The URL shown in these examples is a static URL which should already
  // be URL-encoded. In practice, you will likely have code
  // which assembles your URL from user or web service input
  // and plugs those values into its parameters.
  private static String urlString = "YOUR_URL_TO_SIGN";

  // This variable stores the binary key, which is computed from the string (Base64) key
  private static byte[] key;
  
  public static void main(String[] args) throws IOException,
    InvalidKeyException, NoSuchAlgorithmException, URISyntaxException {
    
    BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
    
    String inputUrl, inputKey = null;

    // For testing purposes, allow user input for the URL.
    // If no input is entered, use the static URL defined above.    
    System.out.println("Enter the URL (must be URL-encoded) to sign: ");
    inputUrl = input.readLine();
    if (inputUrl.equals("")) {
      inputUrl = urlString;
    }
    
    // Convert the string to a URL so we can parse it
    URL url = new URL(inputUrl);
 
    // For testing purposes, allow user input for the private key.
    // If no input is entered, use the static key defined above.   
    System.out.println("Enter the Private key to sign the URL: ");
    inputKey = input.readLine();
    if (inputKey.equals("")) {
      inputKey = keyString;
    }
    
    UrlSigner signer = new UrlSigner(inputKey);
    String request = signer.signRequest(url.getPath(),url.getQuery());
    
    System.out.println("Signed URL :" + url.getProtocol() + "://" + url.getHost() + request);
  }
  
  public UrlSigner(String keyString) throws IOException {
    // Convert the key from 'web safe' base 64 to binary
    keyString = keyString.replace('-', '+');
    keyString = keyString.replace('_', '/');
    System.out.println("Key: " + keyString);
    // Base64 is JDK 1.8 only - older versions may need to use Apache Commons or similar.
    this.key = Base64.getDecoder().decode(keyString);
  }

  public String signRequest(String path, String query) throws NoSuchAlgorithmException,
    InvalidKeyException, UnsupportedEncodingException, URISyntaxException {
    
    // Retrieve the proper URL components to sign
    String resource = path + '?' + query;
    
    // Get an HMAC-SHA1 signing key from the raw key bytes
    SecretKeySpec sha1Key = new SecretKeySpec(key, "HmacSHA1");

    // Get an HMAC-SHA1 Mac instance and initialize it with the HMAC-SHA1 key
    Mac mac = Mac.getInstance("HmacSHA1");
    mac.init(sha1Key);

    // compute the binary signature for the request
    byte[] sigBytes = mac.doFinal(resource.getBytes());

    // base 64 encode the binary signature
    // Base64 is JDK 1.8 only - older versions may need to use Apache Commons or similar.
    String signature = Base64.getEncoder().encodeToString(sigBytes);
    
    // convert the signature to 'web safe' base 64
    signature = signature.replace('+', '-');
    signature = signature.replace('/', '_');
    
    return resource + "&signature=" + signature;
  }
}

Node JS

O exemplo abaixo usa módulos nativos do Node para assinar um URL. Faça o download do código (link em inglês).

'use strict'

const crypto = require('crypto');
const url = require('url');

/**
 * Convert from 'web safe' base64 to true base64.
 *
 * @param  {string} safeEncodedString The code you want to translate
 *                                    from a web safe form.
 * @return {string}
 */
function removeWebSafe(safeEncodedString) {
  return safeEncodedString.replace(/-/g, '+').replace(/_/g, '/');
}

/**
 * Convert from true base64 to 'web safe' base64
 *
 * @param  {string} encodedString The code you want to translate to a
 *                                web safe form.
 * @return {string}
 */
function makeWebSafe(encodedString) {
  return encodedString.replace(/\+/g, '-').replace(/\//g, '_');
}

/**
 * Takes a base64 code and decodes it.
 *
 * @param  {string} code The encoded data.
 * @return {string}
 */
function decodeBase64Hash(code) {
  // "new Buffer(...)" is deprecated. Use Buffer.from if it exists.
  return Buffer.from ? Buffer.from(code, 'base64') : new Buffer(code, 'base64');
}

/**
 * Takes a key and signs the data with it.
 *
 * @param  {string} key  Your unique secret key.
 * @param  {string} data The url to sign.
 * @return {string}
 */
function encodeBase64Hash(key, data) {
  return crypto.createHmac('sha1', key).update(data).digest('base64');
}

/**
 * Sign a URL using a secret key.
 *
 * @param  {string} path   The url you want to sign.
 * @param  {string} secret Your unique secret key.
 * @return {string}
 */
function sign(path, secret) {
  const uri = url.parse(path);
  const safeSecret = decodeBase64Hash(removeWebSafe(secret));
  const hashedSignature = makeWebSafe(encodeBase64Hash(safeSecret, uri.path));
  return url.format(uri) + '&signature=' + hashedSignature;
}

C#

No exemplo abaixo, a biblioteca padrão System.Security.Cryptography é usada para assinar uma solicitação de URL. É preciso converter a codificação Base64 padrão para implementar uma versão compatível com URL. Faça o download do código (link em inglês).

using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace SignUrl {

  public struct GoogleSignedUrl {

    public static string Sign(string url, string keyString) {
      ASCIIEncoding encoding = new ASCIIEncoding();

      // converting key to bytes will throw an exception, need to replace '-' and '_' characters first.
      string usablePrivateKey = keyString.Replace("-", "+").Replace("_", "/");
      byte[] privateKeyBytes = Convert.FromBase64String(usablePrivateKey);

      Uri uri = new Uri(url);
      byte[] encodedPathAndQueryBytes = encoding.GetBytes(uri.LocalPath + uri.Query);

      // compute the hash
      HMACSHA1 algorithm = new HMACSHA1(privateKeyBytes);
      byte[] hash = algorithm.ComputeHash(encodedPathAndQueryBytes);

      // convert the bytes to string and make url-safe by replacing '+' and '/' characters
      string signature = Convert.ToBase64String(hash).Replace("+", "-").Replace("/", "_");
            
      // Add the signature to the existing URI.
      return uri.Scheme+"://"+uri.Host+uri.LocalPath + uri.Query +"&signature=" + signature;
    }
  }

  class Program {

    static void Main() {
    
      // Note: Generally, you should store your private key someplace safe
      // and read them into your code

      const string keyString = "YOUR_PRIVATE_KEY";
  
      // The URL shown in these examples is a static URL which should already
      // be URL-encoded. In practice, you will likely have code
      // which assembles your URL from user or web service input
      // and plugs those values into its parameters.
      const  string urlString = "YOUR_URL_TO_SIGN";
      
      string inputUrl = null;
      string inputKey = null;
    
      Console.WriteLine("Enter the URL (must be URL-encoded) to sign: ");
      inputUrl = Console.ReadLine();
      if (inputUrl.Length == 0) {
        inputUrl = urlString;
      }     
    
      Console.WriteLine("Enter the Private key to sign the URL: ");
      inputKey = Console.ReadLine();
      if (inputKey.Length == 0) {
        inputKey = keyString;
      }
      
      Console.WriteLine(GoogleSignedUrl.Sign(inputUrl,inputKey));
    }
  }
}

Exemplos em outras linguagens

Veja outros exemplos de linguagens no projeto url-signing (link em inglês).

Solução de problemas

Se a sua solicitação estiver incorreta ou fornecer uma assinatura inválida, a API Street View Static retornará um erro HTTP 403 (Forbidden).

Para solucionar o problema, copie o URL da solicitação, remova o parâmetro de consulta signature e gere novamente uma assinatura válida seguindo as instruções abaixo:

Para gerar uma assinatura digital com uma chave de API usando o widget Assinar URL agora no Console do Google Cloud:

  1. Localize o widget Assinar URL agora, conforme descrito na Etapa 1: gerar a Chave secreta de assinatura do URL.
  2. No campo URL, cole o URL da Etapa 2: criar solicitação sem assinatura.
  3. O URL assinado digitalmente aparecerá no campo Seu URL assinado. Lembre-se de fazer uma cópia dele.