URLs e hash

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

Visão geral

As listas do Navegação segura consistem em hashes SHA256 de comprimento variável. (consulte Listar conteúdo). Para verificar um URL em uma lista da Navegação segura (localmente ou no servidor), os clientes precisam primeiro computar o prefixo hash desse URL.

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

  1. Canonizar 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 hash para cada hash completo Consulte Cálculos do prefixo de hash.

Essas etapas refletem o processo que o servidor da Navegação segura usa para manter o Procurar listas.

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 deverá converter o URL para a representação ASCII de punycode. O URL precisa incluir um componente de caminho, ou seja, ele precisa ter uma barra 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/".

Terceiro, remova a porcentagem de escape do URL repetidamente até que ele não tenha mais percentuais de escape.

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 com valores decimais separados por pontos. O cliente deve lidar com qualquer codificação legal de endereço IP, incluindo octal, hexadecimal e menos de quatro componentes.
  4. Minúsculas a string inteira.

Para canonizar o caminho:

  1. Resolver as sequências "/../" e "/./" no caminho por substituindo "/./" com "/" e remover "/../" com o caminho anterior componente.
  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, a porcentagem de escape de todos os caracteres <= ASCII 32, >= 127, "#" ou "%". Os escapes devem 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 de canonizar o URL, a próxima etapa é 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), conforme mostrado nestes 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 possíveis 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 senha e porta serão descartadas. Se o URL incluir parâmetros de consulta, pelo menos uma combinação vai 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 a partir dos ú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 devem ser marcados se o host for um endereço IP.

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

  • 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 acrescentando-o sucessivamente componentes, incluindo uma barra final.

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 tentará estas strings possíveis:

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

Após a criação do conjunto de expressões de sufixo/prefixo, a próxima etapa é calcular o hash SHA256 completo para cada expressão. Confira abaixo um teste de unidade (em pseudo-C) que você pode usar para validar suas cálculos de hash.

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