URL และการแฮช

เอกสารนี้ใช้กับเมธอดต่อไปนี้ Update API (v4): fullHashes.find

ภาพรวม

รายการ Google Safe Browsing ประกอบด้วยแฮช SHA256 ที่มีความยาวแปรผัน (ดูเนื้อหาในรายการ) หากต้องการตรวจสอบ URL กับรายการ Google Safe Browsing (ทั้งในเครื่องหรือในเซิร์ฟเวอร์) ไคลเอ็นต์ต้องคำนวณคำนำหน้าแฮชของ URL นั้นก่อน

ในการคำนวณคำนำหน้าแฮชของ URL ให้ทำตามขั้นตอนต่อไปนี้

  1. กำหนดหน้า Canonical URL (ดูการกำหนดหน้า Canonical)
  2. สร้างคำต่อท้าย/คำนำหน้าสำหรับ URL (โปรดดูนิพจน์คำต่อท้าย/คำนำหน้า)
  3. คำนวณแฮชแบบเต็มสำหรับคำต่อท้าย/คำนำหน้า/นิพจน์แต่ละรายการ (ดูการคำนวณแฮช)
  4. คำนวณคำนำหน้าแฮชสำหรับแฮชแบบเต็มแต่ละรายการ (ดูการคำนวณคำนำหน้าแฮช)

โปรดทราบว่าขั้นตอนเหล่านี้เหมือนกับกระบวนการที่เซิร์ฟเวอร์ Google Safe Browsing ใช้เพื่อรักษารายการ Google Safe Browsing

การกำหนดหน้า Canonical

ในการเริ่มต้น เราถือว่าไคลเอ็นต์ได้แยกวิเคราะห์ URL และทำให้ถูกต้องตาม RFC 2396 หาก URL ใช้ชื่อโดเมนสากล (IDN) ไคลเอ็นต์ควรแปลง URL เป็นการนำเสนอ Punycode แบบ ASCII URL ต้องมีคอมโพเนนต์เส้นทาง นั่นคือต้องมีเครื่องหมายทับปิดท้าย ("http://google.com/")

ขั้นแรก ให้นำอักขระแท็บ (0x09), CR (0x0d) และ LF (0x0a) ออกจาก URL อย่านำลำดับหลีกของอักขระเหล่านี้ออก (เช่น "%0a")

ขั้นที่สอง หาก URL ลงท้ายด้วยส่วนย่อย ให้นำส่วนย่อยออก เช่น ย่อ "http://google.com/#frag" เป็น "http://google.com/"

ขั้นที่สาม ให้ไม่ได้ใช้อักขระหลีกกับ URL แบบเป็นเปอร์เซ็นต์ซ้ำๆ จนกว่าจะไม่มีการใช้อักขระหลีกเปอร์เซ็นต์อีกเลย

วิธีกำหนดชื่อโฮสต์เป็นเวอร์ชัน Canonical

ดึงชื่อโฮสต์จาก URL แล้วต่อด้วย

  1. นำจุดนำหน้าและจุดต่อท้ายทั้งหมดออก
  2. แทนที่จุดติดกันด้วยจุดเดียว
  3. หากแยกวิเคราะห์ชื่อโฮสต์เป็นที่อยู่ IP ได้ ให้ปรับชื่อโฮสต์เป็นค่าทศนิยมที่คั่นด้วยจุด 4 จุด ไคลเอ็นต์ควรใช้การเข้ารหัสที่อยู่ IP ตามกฎหมาย ซึ่งรวมถึงเลขฐานแปด เลขฐานสิบหก และคอมโพเนนต์น้อยกว่า 4 รายการ
  4. ใช้ตัวพิมพ์เล็กทั้งสตริง

วิธีกำหนดเส้นทางเป็นหน้า Canonical

  1. แก้ไขลำดับ "/../" และ "/./" ในเส้นทางโดยแทนที่ "/./" ด้วย "/" และนำ "/../" ออกพร้อมกับคอมโพเนนต์เส้นทางที่อยู่ก่อนหน้า
  2. แทนที่เครื่องหมายทับที่ต่อเนื่องกันด้วยเครื่องหมายทับตัวเดียว

อย่าใช้การกำหนดเส้นทางตามรูปแบบบัญญัติเหล่านี้กับพารามิเตอร์การค้นหา

ใน URL ใช้อักขระหลีกอักขระทั้งหมดที่เป็น <= ASCII 32, >= 127, "#" หรือ "%" ใน URL ส่วนอักขระหลีกควรใช้อักขระฐานสิบหกตัวพิมพ์ใหญ่

ด้านล่างนี้คือการทดสอบเพื่อช่วยตรวจสอบความถูกต้องของการใช้งานการกำหนดเวอร์ชันที่ต้องการ

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

นิพจน์คำต่อท้าย/คำนำหน้า

เมื่อ URL ได้รับการ Canonical แล้ว ขั้นตอนถัดไปคือการสร้างนิพจน์คําต่อท้าย/คํานําหน้า นิพจน์ต่อท้าย/คำนำหน้าแต่ละรายการประกอบด้วยคำต่อท้ายของโฮสต์ (หรือโฮสต์แบบเต็ม) และคำนำหน้าเส้นทาง (หรือเส้นทางแบบเต็ม) ดังที่แสดงในตัวอย่างเหล่านี้

นิพจน์คำต่อท้าย/คำนำหน้านิพจน์ทั่วไปที่เทียบเท่า
a.b/mypath/
http\:\/\/.*\.a\.b\/mypath\/.*
c.d/full/path.html?myparam=a
http\:\/\/.*.c\.d\/full\/path\.html?myparam=a

ไคลเอ็นต์จะสร้างค่าผสมของคำต่อท้ายโฮสต์และคำนำหน้าเส้นทางที่แตกต่างกันได้สูงสุด 30 รายการ ชุดค่าผสมเหล่านี้ใช้เฉพาะคอมโพเนนต์โฮสต์และเส้นทางของ URL สคีม ชื่อผู้ใช้ รหัสผ่าน และพอร์ตจะถูกยกเลิก หาก URL มีพารามิเตอร์การค้นหา อย่างน้อย 1 ชุดค่าผสมจะรวมเส้นทางแบบเต็มและพารามิเตอร์การค้นหา

สำหรับโฮสต์ ไคลเอ็นต์จะลองใช้สตริงที่แตกต่างกันไม่เกิน 5 สตริง ปัจจัยต่างๆ มีดังนี้

  • ชื่อโฮสต์ที่ตรงกันทุกประการใน URL
  • ชื่อโฮสต์สูงสุด 4 รายการที่สร้างโดยเริ่มด้วยองค์ประกอบ 5 รายการสุดท้าย และนำคอมโพเนนต์ที่นำหน้าออกตามลำดับ คุณสามารถข้ามโดเมนระดับบนสุดได้ ไม่ควรตรวจสอบชื่อโฮสต์เพิ่มเติมเหล่านี้หากโฮสต์เป็นที่อยู่ IP

สำหรับเส้นทาง ไคลเอ็นต์จะลองใช้สตริงที่แตกต่างกันไม่เกิน 6 รายการ ได้แก่

  • เส้นทางที่แน่นอนของ URL รวมถึงพารามิเตอร์การค้นหา
  • เส้นทางที่ถูกต้องของ URL โดยไม่มีพารามิเตอร์การค้นหา
  • เส้นทางทั้ง 4 เส้นที่เกิดจากการเริ่มต้นที่ราก (/) และตามด้วยคอมโพเนนต์ของเส้นทางที่ตามมา รวมถึงเครื่องหมายทับปิดท้าย

ตัวอย่างต่อไปนี้แสดงลักษณะการตรวจสอบ

สำหรับ URL http://a.b.c/1/2.html?param=1 ไคลเอ็นต์จะลองใช้สตริงที่เป็นไปได้ต่อไปนี้

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/

สำหรับ URL http://a.b.c.d.e.f.g/1.html ไคลเอ็นต์จะลองใช้สตริงที่เป็นไปได้ต่อไปนี้

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/

สำหรับ URL http://1.2.3.4/1/ ไคลเอ็นต์จะลองใช้สตริงที่เป็นไปได้ต่อไปนี้

1.2.3.4/1/
1.2.3.4/

การคำนวณแฮช

เมื่อสร้างชุดนิพจน์คำต่อท้าย/คำนำหน้าแล้ว ขั้นตอนต่อไปคือการคำนวณแฮช SHA256 แบบเต็มสำหรับแต่ละนิพจน์ การทดสอบ 1 หน่วย (ในรูปแบบ Pseudo-C) ที่คุณใช้ตรวจสอบการคำนวณแฮชได้ระบุไว้ด้านล่าง

ตัวอย่างจาก 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]);

การคำนวณคำนำหน้าแฮช

สุดท้าย ไคลเอ็นต์ต้องคำนวณคำนำหน้าแฮชสำหรับแฮช SHA256 แบบเต็มแต่ละรายการ สําหรับ Google Safe Browsing คำนำหน้าแฮชประกอบด้วยแฮช SHA256 ที่มีนัยสำคัญที่สุด 4-32 ไบต์

ตัวอย่างจาก FIPS-180-2

  • ตัวอย่าง B1 จาก FIPS-180-2
    • ข้อมูลที่ป้อนคือ "กขค"
    • ไดเจสต์ SHA256 คือ ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad
    • คำนำหน้าแฮช 32 บิตคือ ba7816bf
  • ตัวอย่าง B2 จาก FIPS-180-2
    • ข้อมูลที่ป้อนคือ "abcdbcdecdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
    • ไดเจสต์ SHA256 คือ 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
    • คำนำหน้าแฮชแบบ 48 บิตคือ 248d6a61 d206