URLs und Hashing

Dieses Dokument gilt für die Update API (Version 4): fullHashes.find.

Überblick

Die Safe Browsing-Listen bestehen aus SHA256-Hashes variabler Länge (siehe Listeninhalte). Um eine URL anhand einer Safe Browsing-Liste zu prüfen (entweder lokal oder auf dem Server), müssen Clients zuerst das Hash-Präfix dieser URL berechnen.

So berechnen Sie das Hash-Präfix einer URL:

  1. Kanonisieren Sie die URL (siehe Kanonisierung).
  2. Erstellen Sie die Suffix-/Präfix-Ausdrücke für die URL (siehe Suffix-/Präfix-Ausdrücke).
  3. Berechnen Sie den Hashwert in voller Länge für jeden Suffix-/Präfixausdruck (siehe Hash-Berechnungen).
  4. Berechnen Sie das Hash-Präfix für jeden Hash in voller Länge (siehe Hash-Präfix-Berechnungen).

Diese Schritte entsprechen dem Prozess, den der Safe Browsing-Server zur Verwaltung der Safe Browsing-Listen verwendet.

Kanonisierung

Zunächst gehen wir davon aus, dass der Client die URL geparst und gemäß RFC 2396 gültig gemacht hat. Wenn die URL einen internationalisierten Domainnamen (IDN) verwendet, sollte der Client die URL in die ASCII-Punycode-Darstellung konvertieren. Die URL muss eine Pfadkomponente enthalten, also einen abschließenden Schrägstrich („http://google.com/“).

Entfernen Sie zuerst die Zeichen Tabulator (0x09), CR (0x0d) und LF (0x0a) aus der URL. Entfernen Sie keine Escapesequenzen für diese Zeichen (z.B. "%0a").

Zweitens: Wenn die URL in einem Fragment endet, entfernen Sie das Fragment. Kürzen Sie z. B. „http://google.com/#frag“ zu „http://google.com/“.

Drittens: Wiederholen Sie die Escape-Zeichen so lange, bis keine weiteren Escape-Zeichen mehr vorhanden sind.

So kanonisieren Sie den Hostnamen:

Extrahieren Sie den Hostnamen aus der URL und führen Sie dann folgende Schritte aus:

  1. Entfernen Sie alle vor- und nachgestellten Punkte.
  2. Ersetzen Sie aufeinanderfolgende Punkte durch einen einzelnen Punkt.
  3. Wenn der Hostname als IP-Adresse geparst werden kann, normalisieren Sie ihn auf vier durch Punkte getrennte Dezimalwerte. Der Client sollte jede zulässige IP-Adresscodierung einschließlich Oktal, Hexadezimalwert und weniger als vier Komponenten übernehmen.
  4. Verwenden Sie Kleinbuchstaben für den gesamten String.

So kanonisieren Sie den Pfad:

  1. Lösen Sie die Sequenzen "/../" und "/./" im Pfad auf, indem Sie "/./" durch "/" ersetzen und "/../" zusammen mit der vorherigen Pfadkomponente entfernen.
  2. Ersetzen Sie aufeinanderfolgende Schrägstriche durch einen Schrägstrich.

Wenden Sie diese Pfadkanonisierung nicht auf die Suchparameter an.

Maskieren Sie in der URL alle Zeichen, die <= ASCII 32, >= 127, "#" oder "%" sind, mit Escapezeichen (%). Verwenden Sie stattdessen Hexadezimalzeichen in Großbuchstaben.

Im Folgenden finden Sie Tests zur Validierung einer Kanonisierungsimplementierung.

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-/Präfixausdrücke

Nach der Kanonisierung der URL müssen im nächsten Schritt die Suffix-/Präfixausdrücke erstellt werden. Jeder Suffix/Präfixausdruck besteht aus einem Hostsuffix (oder vollständigen Host) und einem Pfadpräfix (oder vollständigen Pfad), wie in diesen Beispielen gezeigt.

Suffix/PräfixausdruckEntsprechender regulärer Ausdruck
a.b/mypath/
http\:\/\/.*\.a\.b\/mypath\/.*
c.d/full/path.html?myparam=a
http\:\/\/.*.c\.d\/full\/path\.html?myparam=a

Der Client bildet bis zu 30 verschiedene Kombinationen aus Hostsuffix und Pfadpräfixen. Bei diesen Kombinationen werden nur die Host- und Pfadkomponenten der URL verwendet. Schema, Nutzername, Passwort und Port werden verworfen. Wenn die URL Suchparameter enthält, enthält mindestens eine Kombination den vollständigen Pfad und die Abfrageparameter.

Für den Host versucht der Client höchstens fünf verschiedene Strings. Sie sind:

  • Der genaue Hostname in der URL.
  • Es werden bis zu vier Hostnamen gebildet, indem mit den letzten fünf Komponenten begonnen und die führende Komponente nacheinander entfernt wird. Die Top-Level-Domain kann übersprungen werden. Diese zusätzlichen Hostnamen sollten nicht geprüft werden, wenn der Host eine IP-Adresse ist.

Für den Pfad versucht der Client höchstens sechs verschiedene Strings. Diese sind:

  • Der genaue Pfad der URL, einschließlich der Suchparameter.
  • Der genaue Pfad der URL ohne Abfrageparameter.
  • Die vier Pfade, die gebildet werden, indem am Stamm (/) begonnen und die Pfadkomponenten nacheinander angefügt werden, einschließlich eines abschließenden Schrägstrichs.

Die folgenden Beispiele veranschaulichen das Überprüfungsverhalten:

Für die URL http://a.b.c/1/2.html?param=1 versucht der Client diese möglichen Strings:

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/

Für die URL http://a.b.c.d.e.f.g/1.html versucht der Client diese möglichen 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/

Für die URL http://1.2.3.4/1/ versucht der Client diese möglichen Strings:

1.2.3.4/1/
1.2.3.4/

Hash-Berechnungen

Nachdem der Satz von Suffix-/Präfix-Ausdrücken erstellt wurde, wird im nächsten Schritt der SHA256-Hash in voller Länge für jeden Ausdruck berechnet. Unten finden Sie einen Einheitentest (in Pseudo-C), mit dem Sie Ihre Hash-Berechnungen validieren können.

Beispiel des 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]);

Hash-Präfixberechnungen

Schließlich muss der Client das Hash-Präfix für jeden SHA256-Hash in voller Länge berechnen. Bei Safe Browsing besteht ein Hash-Präfix aus den wichtigsten 4–32 Byte eines SHA256-Hashs.

Beispiel des FIPS-180-2:

  • Beispiel B1 aus FIPS-180-2
    • Die Eingabe ist "abc".
    • Der SHA256-Digest lautet ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad.
    • Das 32-Bit-Hash-Präfix lautet ba7816bf.
  • Beispiel B2 aus FIPS-180-2
    • Die Eingabe ist "abcdbcdecdefdefgefghfghighijhijkljklmklmnlmnomnopnopq".
    • Der SHA256-Digest lautet 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1.
    • Das 48-Bit-Hash-Präfix ist 248d6a61 d206.