URL y codificación hash

Este documento se aplica al siguiente método: API de Update (v4): fullHashes.find.

Descripción general

Las listas de la Navegación segura constan de hash SHA256 de longitud variable (consulta Contenido de la lista). Para comparar una URL con una lista de Navegación segura (ya sea de forma local o en el servidor), los clientes primero deben procesar el prefijo hash de esa URL.

Para calcular el prefijo de hash de una URL, sigue estos pasos:

  1. Canonicaliza la URL (consulta Canonicalización).
  2. Crea las expresiones de sufijo o prefijo para la URL (consulta Expresiones de sufijo o prefijo).
  3. Calcula el hash de longitud completa para cada expresión de sufijo o prefijo (consulta Cálculos de hash).
  4. Calcula el prefijo de hash para cada hash completo (consulta Cálculos de prefijo de hash).

Ten en cuenta que estos pasos reflejan el proceso que usa el servidor de Navegación segura para mantener sus listas.

Canonicalización

Para comenzar, suponemos que el cliente analizó la URL y la hizo válida según el estándar RFC 2396. Si la URL usa un nombre de dominio internacionalizado (IDN), el cliente debe convertir la URL a la representación ASCII de Punycode. La URL debe incluir un componente de ruta de acceso, es decir, debe tener una barra final ("http://google.com/").

Primero, quita los caracteres tabulador (0x09), CR (0x0d) y LF (0x0a) de la URL. No elimines las secuencias de escape para estos caracteres (por ejemplo, '%0a').

En segundo lugar, si la URL termina en un fragmento, quítalo. Por ejemplo, abrevia "http://google.com/#frag" por "http://google.com/".

Tercero, de forma reiterada, sin escapes porcentuales de la URL hasta que no haya más escapes porcentuales.

Para canonicalizar el nombre de host, sigue estos pasos:

Extrae el nombre de host de la URL y luego haz lo siguiente:

  1. Quita todos los puntos iniciales y finales.
  2. Reemplaza los puntos consecutivos por un solo punto.
  3. Si el nombre de host se puede analizar como una dirección IP, normalízalo a 4 valores decimales separados por puntos. El cliente debe manejar cualquier codificación de dirección IP legal, incluida la octal, la hexadecimal y menos de cuatro componentes.
  4. Pon en minúscula toda la string.

Para canonicalizar la ruta, sigue estos pasos:

  1. Resuelve las secuencias "/../" y "/./" en la ruta. Para ello, reemplaza "/./" por "/" y quita "/../" junto con el componente de la ruta de acceso anterior.
  2. Reemplaza las ejecuciones de barras consecutivas por un solo carácter de barra.

No apliques estas canonicalizaciones de ruta a los parámetros de búsqueda.

En la URL, se deben escapar todos los caracteres que sean <= ASCII 32, >= 127, "#" o "%". Los caracteres de escape deben usar caracteres hexadecimales en mayúsculas.

A continuación, se presentan pruebas que ayudan a validar una implementación de canonicalización.

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";

Suffix/prefix expressions

Una vez que se canonicaliza la URL, el siguiente paso es crear las expresiones de sufijo o prefijo. Cada expresión de sufijo o prefijo consta de un sufijo de host (o host completo) y un prefijo de ruta de acceso (o ruta de acceso completa), como se muestra en estos ejemplos.

Expresión de sufijo o prefijoExpresión regular equivalente
a.b/mypath/
http\:\/\/.*\.a\.b\/mypath\/.*
c.d/full/path.html?myparam=a
http\:\/\/.*.c\.d\/full\/path\.html?myparam=a

El cliente formará hasta 30 combinaciones posibles de sufijo de host y prefijo de ruta de acceso diferentes. Estas combinaciones solo usan los componentes de host y ruta de acceso de la URL. Se descartan el esquema, el nombre de usuario, la contraseña y el puerto. Si la URL incluye parámetros de consulta, al menos una combinación incluirá la ruta de acceso completa y los parámetros de búsqueda.

Para el host, el cliente intentará como máximo con cinco strings diferentes. Son:

  • El nombre de host exacto que aparece en la URL
  • Hasta cuatro nombres de host formados a partir de los últimos cinco componentes y, luego, quitando el componente principal. Se puede omitir el dominio de nivel superior. Estos nombres de host adicionales no se deben verificar si el host es una dirección IP.

Para la ruta, el cliente intentará como máximo con seis strings diferentes. Son los siguientes:

  • La ruta exacta de la URL, incluidos los parámetros de búsqueda.
  • La ruta exacta de la URL, sin parámetros de búsqueda.
  • Las cuatro rutas formadas por comenzar en la raíz (/) y, luego, anexar componentes de ruta de acceso, incluida una barra final.

En los siguientes ejemplos, se muestra el comportamiento de las verificaciones:

Para la URL http://a.b.c/1/2.html?param=1, el cliente probará estas strings posibles:

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 la URL http://a.b.c.d.e.f.g/1.html, el cliente probará estas strings posibles:

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 la URL http://1.2.3.4/1/, el cliente probará estas strings posibles:

1.2.3.4/1/
1.2.3.4/

Cálculos de hash

Una vez que se creó el conjunto de expresiones de sufijo o prefijo, el siguiente paso es calcular el hash SHA256 de longitud completa para cada expresión. A continuación, se proporciona una prueba de unidades (en seudo-C) que puedes usar para validar tus cálculos de hash.

Ejemplos 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 prefijo hash

Por último, el cliente debe calcular el prefijo de hash para cada hash SHA256 de longitud completa. En el caso de la Navegación segura, un prefijo de hash consta de los 4 a 32 bytes más significativos de un hash SHA256.

Ejemplos de FIPS-180-2:

  • Ejemplo B1 de FIPS-180-2
    • La entrada es "abc".
    • El resumen SHA256 es ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad.
    • El prefijo hash de 32 bits es ba7816bf.
  • Ejemplo B2 de FIPS-180-2
    • La entrada es “abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq”.
    • El resumen SHA256 es 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1.
    • El prefijo hash de 48 bits es 248d6a61 d206.