URL-адреса и хеширование

Этот документ относится к следующему методу: Обновление API (v4) : fullHashes.find .

Обзор

Списки безопасного просмотра состоят из хэшей SHA256 переменной длины (см. Содержание списков ). Чтобы проверить URL-адрес на соответствие списку безопасного просмотра (локально или на сервере), клиенты должны сначала вычислить хеш-префикс этого URL-адреса.

Чтобы вычислить хеш-префикс URL-адреса, выполните следующие действия:

  1. Канонизировать URL-адрес (см. Канонизация ).
  2. Создайте выражения суффикса/префикса для URL-адреса (см. Выражения суффикса/префикса ).
  3. Вычислите полный хэш для каждого выражения суффикса/префикса (см. «Вычисления хеша »).
  4. Вычислите префикс хеша для каждого полного хеша (см. Вычисления префикса хеша ).

Обратите внимание, что эти шаги отражают процесс, который сервер безопасного просмотра использует для обслуживания списков безопасного просмотра.

Канонизация

Для начала мы предполагаем, что клиент проанализировал URL-адрес и сделал его действительным в соответствии с RFC 2396. Если URL-адрес использует интернационализированное доменное имя (IDN), клиент должен преобразовать URL-адрес в представление Punycode ASCII. URL-адрес должен включать компонент пути; то есть он должен иметь косую черту ("http://google.com/").

Сначала удалите из URL-адреса символы табуляции (0x09), CR (0x0d) и LF (0x0a). Не удаляйте escape-последовательности для этих символов (например, «%0a»).

Во-вторых, если URL-адрес заканчивается фрагментом, удалите этот фрагмент. Например, сократите «http://google.com/#frag» до «http://google.com/».

В-третьих, несколько раз удаляйте процентное экранирование URL-адреса, пока на нем не останется процентного экранирования.

Чтобы канонизировать имя хоста:

Извлеките имя хоста из URL-адреса, а затем:

  1. Удалите все ведущие и конечные точки.
  2. Замените последовательные точки одной точкой.
  3. Если имя хоста можно проанализировать как IP-адрес, нормализуйте его до 4 десятичных значений, разделенных точками. Клиент должен обрабатывать любую допустимую кодировку IP-адреса, включая восьмеричную, шестнадцатеричную и менее четырех компонентов.
  4. В нижнем регистре всю строку.

Чтобы канонизировать путь:

  1. Разрешите последовательности «/../» и «/./» в пути, заменив «/./» на «/» и удалив «/../» вместе с предыдущим компонентом пути.
  2. Замените серию последовательных косых черт одним символом косой черты.

Не применяйте канонизацию пути к параметрам запроса.

В URL-адресе экранируйте процентами все символы <= ASCII 32, >= 127, "#" или "%". В escape-символах следует использовать шестнадцатеричные символы верхнего регистра.

Ниже приведены тесты, помогающие проверить реализацию канонизации.

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-адреса следующим шагом будет создание выражений суффикса/префикса. Каждое выражение суффикса/префикса состоит из суффикса хоста (или полного хоста) и префикса пути (или полного пути), как показано в этих примерах.

Суффиксное/префиксное выражение Эквивалентное регулярное выражение
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-адрес включает параметры запроса, то хотя бы одна комбинация будет включать полный путь и параметры запроса.

Для хоста клиент будет пробовать не более пяти разных строк. Они есть:

  • Точное имя хоста в URL.
  • До четырех имен хостов формируются путем начала с последних пяти компонентов и последовательного удаления ведущего компонента. Домен верхнего уровня можно пропустить. Эти дополнительные имена хостов не следует проверять, если хост является IP-адресом.

Для пути клиент попробует не более шести разных строк. Они есть:

  • Точный путь URL-адреса, включая параметры запроса.
  • Точный путь URL-адреса без параметров запроса.
  • Четыре пути формируются путем начала с корня (/) и последовательного добавления компонентов пути, включая косую черту в конце.

Следующие примеры иллюстрируют поведение проверки:

Для URL-адреса http://abc/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://abcdefg/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 для каждого выражения. Модульный тест (на псевдо-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. Для безопасного просмотра префикс хеша состоит из старших 4–32 байтов хеша SHA256.

Примеры из FIPS-180-2 :

  • Пример B1 из FIPS-180-2
    • Ввод: «abc».
    • Дайджест SHA256: ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad.
    • 32-битный хэш-префикс — ba7816bf.
  • Пример B2 из FIPS-180-2
    • Ввод: «abcdbcdecdefdefgefgefghfghighijhijkijkljklmklmnlmnomnopnopq».
    • Дайджест SHA256: 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1.
    • 48-битный префикс хеша — 248d6a61 d206.