URLs e hash

Este documento se aplica ao seguinte método: API Update (v4): fullHashes.find.

Informações gerais

As listas da Navegação segura consistem em hashes SHA256 de tamanho variável. Consulte Conteúdo da lista. Para verificar um URL em uma lista da Navegação segura (local ou no servidor), os clientes precisam primeiro calcular o prefixo de hash desse URL.

Para calcular o prefixo de hash de um URL, siga estas etapas:

  1. Canonize o URL. Consulte Canonização.
  2. Crie as expressões de sufixo/prefixo para o URL (consulte Expressões de sufixo/prefixo).
  3. Calcule o hash completo para cada expressão de sufixo/prefixo. Consulte Cálculos de hash.
  4. Calcule o prefixo de cada hash completo. Consulte Cálculos de prefixos de hash.

Essas etapas espelham o processo que o servidor da Navegação segura usa para manter as listas do recurso.

Canonização

Para começar, presumimos que o cliente analisou o URL e o tornou válido de acordo com a RFC 2396. Se o URL usar um nome de domínio internacionalizado (IDN, na sigla em inglês), o cliente precisará converter o URL na representação ASCII Punycode. O URL precisa incluir um componente de caminho, ou seja, ter uma barra no final ("http://google.com/").

Primeiro, remova os caracteres Tab (0x09), CR (0x0d) e LF (0x0a) do URL. Não remova sequências de escape para esses caracteres (por exemplo, '%0a').

Segundo, se o URL terminar em um fragmento, remova o fragmento. Por exemplo, encurte "http://google.com/#frag" para "http://google.com/".

Em terceiro lugar, remova o escape por cento do URL repetidamente até que ele não tenha mais escapes percentuais.

Para canonizar o nome do host:

Extraia o nome do host do URL e:

  1. Remova todos os pontos iniciais e finais.
  2. Substitua os pontos consecutivos por um único ponto.
  3. Se o nome do host puder ser analisado como um endereço IP, Normalize-o para valores decimais separados por quatro pontos. O cliente precisa lidar com qualquer codificação legal de endereços IP, incluindo octal, hexadecimal e menos de quatro componentes.
  4. Minúsculas a string inteira.

Para canonizar o caminho, faça o seguinte:

  1. Resolva as sequências "/../" e "/./" no caminho substituindo "/./" por "/" e removendo "/../" com o componente de caminho anterior.
  2. Substitua execuções de barras consecutivas por uma única barra.

Não aplique essas canonizações de caminho aos parâmetros de consulta.

No URL, use um escape percentual de todos os caracteres <= ASCII 32, >= 127, "#" ou "%". Os escapes precisam usar caracteres hexadecimais maiúsculos.

Veja abaixo os testes para validar uma implementação de canonização.

Canonicalize("http://host/%25%32%35") = "http://host/%25";
Canonicalize("http://host/%25%32%35%25%32%35") = "http://host/%25%25";
Canonicalize("http://host/%2525252525252525") = "http://host/%25";
Canonicalize("http://host/asdf%25%32%35asd") = "http://host/asdf%25asd";
Canonicalize("http://host/%%%25%32%35asd%%") = "http://host/%25%25%25asd%25%25";
Canonicalize("http://www.google.com/") = "http://www.google.com/";
Canonicalize("http://%31%36%38%2e%31%38%38%2e%39%39%2e%32%36/%2E%73%65%63%75%72%65/%77%77%77%2E%65%62%61%79%2E%63%6F%6D/") = "http://168.188.99.26/.secure/www.ebay.com/";
Canonicalize("http://195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/") = "http://195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/";
Canonicalize("http://host%23.com/%257Ea%2521b%2540c%2523d%2524e%25f%255E00%252611%252A22%252833%252944_55%252B") = "http://host%23.com/~a!b@c%23d$e%25f^00&11*22(33)44_55+";
Canonicalize("http://3279880203/blah") = "http://195.127.0.11/blah";
Canonicalize("http://www.google.com/blah/..") = "http://www.google.com/";
Canonicalize("www.google.com/") = "http://www.google.com/";
Canonicalize("www.google.com") = "http://www.google.com/";
Canonicalize("http://www.evil.com/blah#frag") = "http://www.evil.com/blah";
Canonicalize("http://www.GOOgle.com/") = "http://www.google.com/";
Canonicalize("http://www.google.com.../") = "http://www.google.com/";
Canonicalize("http://www.google.com/foo\tbar\rbaz\n2") ="http://www.google.com/foobarbaz2";
Canonicalize("http://www.google.com/q?") = "http://www.google.com/q?";
Canonicalize("http://www.google.com/q?r?") = "http://www.google.com/q?r?";
Canonicalize("http://www.google.com/q?r?s") = "http://www.google.com/q?r?s";
Canonicalize("http://evil.com/foo#bar#baz") = "http://evil.com/foo";
Canonicalize("http://evil.com/foo;") = "http://evil.com/foo;";
Canonicalize("http://evil.com/foo?bar;") = "http://evil.com/foo?bar;";
Canonicalize("http://\x01\x80.com/") = "http://%01%80.com/";
Canonicalize("http://notrailingslash.com") = "http://notrailingslash.com/";
Canonicalize("http://www.gotaport.com:1234/") = "http://www.gotaport.com/";
Canonicalize("  http://www.google.com/  ") = "http://www.google.com/";
Canonicalize("http:// leadingspace.com/") = "http://%20leadingspace.com/";
Canonicalize("http://%20leadingspace.com/") = "http://%20leadingspace.com/";
Canonicalize("%20leadingspace.com/") = "http://%20leadingspace.com/";
Canonicalize("https://www.securesite.com/") = "https://www.securesite.com/";
Canonicalize("http://host.com/ab%23cd") = "http://host.com/ab%23cd";
Canonicalize("http://host.com//twoslashes?more//slashes") = "http://host.com/twoslashes?more//slashes";

Expressões de sufixo/prefixo

Depois que o URL for canonizado, a próxima etapa será criar as expressões de sufixo/prefixo. Cada expressão de sufixo/prefixo consiste em um sufixo de host (ou host completo) e um prefixo de caminho (ou caminho completo), como mostrado nos exemplos.

Expressão de sufixo/prefixoExpressão regular equivalente
a.b/mypath/
http\:\/\/.*\.a\.b\/mypath\/.*
c.d/full/path.html?myparam=a
http\:\/\/.*.c\.d\/full\/path\.html?myparam=a

O cliente vai formar até 30 combinações diferentes de sufixo de host e prefixo de caminho. Essas combinações usam apenas os componentes de host e caminho do URL. O esquema, o nome de usuário, a senha e a porta serão descartados. Se o URL incluir parâmetros de consulta, pelo menos uma combinação incluirá o caminho completo e os parâmetros de consulta.

Para o host, o cliente tentará no máximo cinco strings diferentes. Elas são:

  • O nome do host exato no URL.
  • Até quatro nomes de host formados começando com os últimos cinco componentes e removendo sucessivamente o componente principal. O domínio de nível superior pode ser ignorado. Esses outros nomes de host não poderão ser verificados se o host for um endereço IP.

Para o caminho, o cliente tentará no máximo seis strings diferentes. São elas:

  • O caminho exato do URL, incluindo os parâmetros de consulta.
  • O caminho exato do URL, sem parâmetros de consulta.
  • Os quatro caminhos formados começando na raiz (/) e anexando sucessivamente componentes do caminho, incluindo uma barra à direita.

Os exemplos a seguir ilustram o comportamento da verificação:

Para o URL http://a.b.c/1/2.html?param=1, o cliente tentará estas strings possíveis:

a.b.c/1/2.html?param=1
a.b.c/1/2.html
a.b.c/
a.b.c/1/
b.c/1/2.html?param=1
b.c/1/2.html
b.c/
b.c/1/

Para o URL http://a.b.c.d.e.f.g/1.html, o cliente vai tentar estas possíveis strings:

a.b.c.d.e.f.g/1.html
a.b.c.d.e.f.g/
(Note: skip b.c.d.e.f.g, since we'll take only the last five hostname components, and the full hostname)
c.d.e.f.g/1.html
c.d.e.f.g/
d.e.f.g/1.html
d.e.f.g/
e.f.g/1.html
e.f.g/
f.g/1.html
f.g/

Para o URL http://1.2.3.4/1/, o cliente vai tentar estas possíveis strings:

1.2.3.4/1/
1.2.3.4/

Cálculos de hash

Depois que o conjunto de expressões de sufixo/prefixo for criado, a próxima etapa será calcular o hash SHA256 completo para cada expressão. Um teste de unidade (em pseudo-C) que pode ser usado para validar seus cálculos de hash é fornecido abaixo.

Exemplos de FIPS-180-2:

Unit Test (in pseudo-C)

// Example B1 from FIPS-180-2
string input1 = "abc";
string output1 = TruncatedSha256Prefix(input1, 32);
int expected1[] = { 0xba, 0x78, 0x16, 0xbf };
assert(output1.size() == 4);  // 4 bytes == 32 bits
for (int i = 0; i < output1.size(); i++) assert(output1[i] == expected1[i]);

// Example B2 from FIPS-180-2
string input2 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
string output2 = TruncatedSha256Prefix(input2, 48);
int expected2[] = { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06 };
assert(output2.size() == 6);
for (int i = 0; i < output2.size(); i++) assert(output2[i] == expected2[i]);

// Example B3 from FIPS-180-2
string input3(1000000, 'a');  // 'a' repeated a million times
string output3 = TruncatedSha256Prefix(input3, 96);
int expected3[] = { 0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92,
                    0x81, 0xa1, 0xc7, 0xe2 };
assert(output3.size() == 12);
for (int i = 0; i < output3.size(); i++) assert(output3[i] == expected3[i]);

Cálculos de prefixo de hash

Por fim, o cliente precisa calcular o prefixo de hash para cada hash SHA256 completo. Para a navegação segura, um prefixo de hash consiste nos 4 a 32 bytes mais significativos de um hash SHA256.

Exemplos de FIPS-180-2:

  • Exemplo B1 de FIPS-180-2
    • A entrada é "abc".
    • O resumo SHA256 é ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad.
    • O prefixo de hash de 32 bits é ba7816bf.
  • Exemplo B2 de FIPS-180-2
    • A entrada é "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".
    • O resumo SHA256 é 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1.
    • O prefixo de hash de 48 bits é 248d6a61 d206.