URL dan Hashing

Dokumen ini berlaku untuk metode berikut: Update API (v4): fullHashes.find.

Ringkasan

Daftar Safe Browsing terdiri dari hash SHA256 dengan panjang variabel (lihat Daftar Konten). Untuk memeriksa URL terhadap daftar Safe Browsing (secara lokal atau di server), klien harus terlebih dahulu menghitung awalan hash URL tersebut.

Untuk menghitung awalan hash URL, ikuti langkah-langkah berikut:

  1. Lakukan kanonikalisasi URL (lihat Kanonikalisasi).
  2. Membuat ekspresi akhiran/awalan untuk URL (lihat Ekspresi Akhiran/Akhiran).
  3. Menghitung hash panjang penuh untuk setiap ekspresi akhiran/awalan (lihat Komputasi Hash).
  4. Hitung awalan hash untuk setiap hash lengkap (lihat Komputasi Awalan Hash).

Perhatikan bahwa langkah-langkah ini mencerminkan proses yang digunakan server Safe Browsing untuk mengelola daftar Safe Browsing.

Kanonikalisasi

Untuk memulai, kami asumsikan bahwa klien telah menguraikan URL dan membuatnya valid sesuai dengan RFC 2396. Jika URL menggunakan nama domain internasional (IDN), klien harus mengonversi URL ke representasi Punycode ASCII. URL harus menyertakan komponen jalur; artinya, harus memiliki garis miring terbalik ("http://google.com/").

Pertama, hapus karakter tab (0x09), CR (0x0d), dan LF (0x0a) dari URL. Jangan hapus urutan escape untuk karakter ini (misalnya, '%0a').

Kedua, jika URL berakhir dengan fragmen, hapus fragmen tersebut. Misalnya, perpendek "http://google.com/#frag" ke "http://google.com/".

Ketiga, berulang kali menggunakan persen-unescape URL hingga tidak ada lagi escape persen.

Untuk melakukan kanonikalisasi nama host:

Ekstrak nama host dari URL, lalu:

  1. Hapus semua titik di bagian awal dan akhir.
  2. Mengganti titik berurutan dengan satu titik.
  3. Jika nama host dapat diuraikan sebagai alamat IP, normalisasikan menjadi 4 nilai desimal yang dipisahkan titik. Klien harus menangani pengkodean alamat IP resmi, termasuk oktal, heksa, dan kurang dari empat komponen.
  4. Mengubah seluruh string menjadi huruf kecil.

Untuk melakukan kanonikalisasi jalur:

  1. Selesaikan urutan "/../" dan "/./" di jalur dengan mengganti "/./" dengan "/", dan menghapus "/../" beserta komponen jalur sebelumnya.
  2. Ganti garis miring yang berurutan dengan satu karakter garis miring.

Jangan terapkan kanonisasi jalur ini ke parameter kueri.

Di URL, gunakan escape persentase untuk semua karakter yang <= ASCII 32, >= 127, "#", atau "%". Escape harus menggunakan karakter heksadesimal huruf besar.

Berikut adalah pengujian untuk membantu memvalidasi implementasi kanonikalisasi.

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

Ekspresi akhiran/awalan

Setelah URL dikanonikalisasi, langkah berikutnya adalah membuat ekspresi akhiran/awalan. Masing-masing ekspresi akhiran/awalan terdiri dari akhiran host (atau host lengkap) dan awalan jalur (atau jalur lengkap) sebagaimana ditunjukkan dalam contoh ini.

Ekspresi Akhiran/AwalanEkspresi Reguler Setara
a.b/mypath/
http\:\/\/.*\.a\.b\/mypath\/.*
c.d/full/path.html?myparam=a
http\:\/\/.*.c\.d\/full\/path\.html?myparam=a

Klien akan membentuk hingga 30 kemungkinan kombinasi awalan jalur dan akhiran host yang berbeda. Kombinasi ini hanya menggunakan komponen host dan jalur URL. Skema, nama pengguna, sandi, dan port akan dihapus. Jika URL menyertakan parameter kueri, setidaknya satu kombinasi akan menyertakan jalur lengkap dan parameter kueri.

Untuk host, klien akan mencoba maksimal lima string yang berbeda. Bagian-bagian tersebut adalah:

  • Nama host yang tepat di URL.
  • Hingga empat nama {i>host<i} yang dibentuk dengan memulai dari lima komponen terakhir dan secara berurutan menghapus komponen utama. Domain level teratas dapat dilewati. Ini nama {i>host <i}tambahan tidak perlu diperiksa jika {i>host <i}adalah alamat IP.

Untuk jalur, klien akan mencoba maksimal enam string berbeda. Yaitu:

  • Jalur URL yang tepat, termasuk parameter kueri.
  • Jalur URL yang tepat, tanpa parameter kueri.
  • Keempat jalur yang dibentuk dengan memulai dari akar (/) dan menambahkan jalur secara berurutan komponen, termasuk garis miring.

Contoh berikut menggambarkan perilaku pemeriksaan:

Untuk URL http://a.b.c/1/2.html?param=1, klien akan mencoba tindakan ini kemungkinan string:

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/

Untuk URL http://a.b.c.d.e.f.g/1.html, klien akan mencoba tindakan berikut 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/

Untuk URL http://1.2.3.4/1/, klien akan mencoba kemungkinan string berikut:

1.2.3.4/1/
1.2.3.4/

Komputasi {i>hash<i}

Setelah kumpulan ekspresi akhiran/awalan dibuat, langkah berikutnya adalah menghitung hash SHA256 berdurasi penuh untuk setiap ekspresi. Pengujian unit (dalam pseudo-C) yang dapat Anda gunakan untuk memvalidasi komputasi {i>hash <i}disediakan di bawah ini.

Contoh dari 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]);

Komputasi awalan hash

Terakhir, klien perlu menghitung awalan hash untuk setiap hash SHA256 berdurasi penuh. Untuk Aman Penjelajahan, awalan hash terdiri dari 4-32 byte paling signifikan dari hash SHA256.

Contoh dari FIPS-180-2:

  • Contoh B1 dari FIPS-180-2
    • Input adalah "abc".
    • Ringkasan SHA256 adalah ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad.
    • Awalan hash 32-bit adalah ba7816bf.
  • Contoh B2 dari FIPS-180-2
    • Input adalah "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".
    • Ringkasan SHA256 adalah 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1.
    • Awalan hash 48-bit adalah 248d6a61 d206.