URL e hashing

Questo documento si applica al seguente metodo: API Update (v4): fullHashes.find.

Panoramica

Gli elenchi di Navigazione sicura sono composti da hash SHA256 di lunghezza variabile (consulta la sezione Contenuti dell'elenco). Per confrontare un URL con un elenco di Navigazione sicura (in locale o sul server), i client devono prima calcolare il prefisso hash dell'URL.

Per calcolare il prefisso hash di un URL:

  1. Canonicalizza l'URL (consulta la sezione Canonicalizzazione).
  2. Crea le espressioni di suffisso/prefisso per l'URL (consulta la sezione Espressioni suffisso/prefisso).
  3. Calcola l'hash completo per ogni espressione di suffisso/prefisso (consulta Calcolo dell'hash).
  4. Calcola il prefisso hash per ogni hash completo (consulta Computazioni del prefisso hash).

Tieni presente che questi passaggi rispecchiano la procedura utilizzata dal server di Navigazione sicura per gestire gli elenchi di Navigazione sicura.

Canonicalizzazione

Per iniziare, supponiamo che il client abbia analizzato l'URL e lo abbia reso valido in base allo standard RFC 2396. Se l'URL utilizza un nome di dominio internazionalizzato (IDN), il client deve convertire l'URL nella rappresentazione Punycode ASCII. L'URL deve includere un componente del percorso, ovvero una barra finale ("http://google.com/").

Innanzitutto, rimuovi i caratteri Tab (0x09), CR (0x0d) e LF (0x0a) dall'URL. Non rimuovere le sequenze di escape per questi caratteri (ad es. "%0a").

In secondo luogo, se l'URL termina con un frammento, rimuovilo. Ad esempio, accorcia "http://google.com/#frag" in "http://google.com/".

Terzo, elimina ripetutamente la percentuale di escape dell'URL fino a quando non contiene più caratteri di escape percentuali.

Per canonicalizzare il nome host:

Estrai il nome host dall'URL, quindi:

  1. Rimuovi tutti i punti iniziali e finali.
  2. Sostituisci i punti consecutivi con un singolo punto.
  3. Se il nome host può essere analizzato come indirizzo IP, normalizzalo in quattro valori decimali separati da punti. Il client deve gestire qualsiasi codifica legale di indirizzi IP, inclusi ottale, esadecimale e meno di quattro componenti.
  4. Scrivi l'intera stringa in minuscolo.

Per canonizzare il percorso:

  1. Risolvi le sequenze "/../" e "/./" nel percorso sostituendo "/./" con "/" e rimuovendo "/../" insieme al componente del percorso precedente.
  2. Sostituisci le esecuzioni di barre consecutive con una barra singola.

Non applicare queste canonicalizzazioni dei percorsi ai parametri di query.

Nell'URL, esegui l'escape di tutti i caratteri <= ASCII 32, >= 127, "#" o "%". Gli escape devono utilizzare caratteri esadecimali maiuscoli.

Di seguito sono riportati alcuni test che consentono di convalidare l'implementazione di una canonicalizzazione.

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

Espressioni suffisso/prefisso

Dopo che l'URL è stato canonico, il passaggio successivo consiste nel creare le espressioni di suffisso/prefisso. Ogni suffisso/espressione di prefisso è composta da un suffisso host (o host completo) e da un prefisso di percorso (o percorso completo) come mostrato in questi esempi.

Espressione suffisso/prefissoEspressione regolare equivalente
a.b/mypath/
http\:\/\/.*\.a\.b\/mypath\/.*
c.d/full/path.html?myparam=a
http\:\/\/.*.c\.d\/full\/path\.html?myparam=a

Il client formerà fino a 30 diverse combinazioni possibili di suffisso host e prefisso percorso. Queste combinazioni utilizzano solo i componenti host e percorso dell'URL. Lo schema, il nome utente, la password e la porta vengono eliminati. Se l'URL include parametri di query, almeno una combinazione includerà il percorso completo e i parametri di query.

Per l'host, il client proverà al massimo cinque stringhe diverse. Questi sono:

  • Il nome host esatto nell'URL.
  • Sono formati fino a quattro nomi host, partendo dagli ultimi cinque componenti e rimuovendo successivamente il componente principale. Il dominio di primo livello può essere ignorato. Questi nomi host aggiuntivi non devono essere controllati se l'host è un indirizzo IP.

Per il percorso, il client proverà al massimo sei stringhe diverse. Questi sono:

  • Il percorso esatto dell'URL, inclusi i parametri di ricerca.
  • Il percorso esatto dell'URL, senza parametri di ricerca.
  • I quattro percorsi formati partendo dalla radice (/) e aggiungendo successivamente i componenti, inclusa una barra finale.

I seguenti esempi illustrano il comportamento di verifica:

Per l'URL http://a.b.c/1/2.html?param=1, il client proverà queste possibili stringhe:

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/

Per l'URL http://a.b.c.d.e.f.g/1.html, il client proverà queste possibili stringhe:

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/

Per l'URL http://1.2.3.4/1/, il client proverà queste possibili stringhe:

1.2.3.4/1/
1.2.3.4/

Calcoli hash

Una volta creato il set di espressioni di suffisso/prefisso, il passaggio successivo consiste nel calcolare l'hash SHA256 completo per ogni espressione. Di seguito è riportato un test delle unità (in pseudo-C) che puoi utilizzare per convalidare i calcoli dell'hash.

Esempi da 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]);

Calcoli per prefissi hash

Infine, il client deve calcolare il prefisso hash per ogni hash SHA256 completo. Per Navigazione sicura, un prefisso hash è costituito dai 4-32 byte più significativi di un hash SHA256.

Esempi da FIPS-180-2:

  • Esempio B1 da FIPS-180-2
    • Il valore è "abc".
    • Il digest SHA256 è ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad.
    • Il prefisso hash a 32 bit è ba7816bf.
  • Esempio B2 da FIPS-180-2
    • L'input è "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".
    • Il digest SHA256 è 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1.
    • Il prefisso hash a 48 bit è 248d6a61 d206.