Bezpieczne przeglądanie w Google w wersji 5 wymaga od klienta utrzymywania lokalnej bazy danych, z wyjątkiem sytuacji, gdy klient wybierze tryb czasu rzeczywistego bez przechowywania danych. Format i miejsce przechowywania tej lokalnej bazy danych zależy od klienta. Zawartość tej lokalnej bazy danych można porównać do folderu zawierającego różne listy w postaci plików, a zawartość tych plików to ciągi znaków identyfikatorów SHA-256 lub ich odpowiadające im prefiksy z 4-bajtowym prefiksem identyfikatora, który jest najczęściej używaną długością identyfikatora.
Dostępne listy
Listy są identyfikowane przez ich nazwy, które są zgodne z konwencją nazewnictwa, w której nazwa zawiera sufiks wskazujący długość hasha, jakiego należy się spodziewać na liście. Listy haszy o tym samym typie zagrożenia, ale o różnej długości hasza będą miały oddzielne nazwy i będą kwalifikowane za pomocą sufiksu wskazującego długość hasza.
Dostępne są następujące listy do użycia z metodami listy haszowanych adresów.
Nazwa listy | Odpowiadające wartościom v4 ThreatType wyliczenie |
Opis |
---|---|---|
gc-32b |
Brak | Ta lista jest listą globalnego magazynu podręcznego. Jest to specjalna lista używana tylko w trybie działania w czasie rzeczywistym. |
se-4b |
SOCIAL_ENGINEERING |
Ta lista zawiera zagrożenia typu SOCIAL_ENGINEERING. |
mw-4b |
MALWARE |
Ta lista zawiera zagrożenia typu MALWARE na platformach komputerów stacjonarnych. |
uws-4b |
UNWANTED_SOFTWARE |
Ta lista zawiera zagrożenia typu UNWANTED_SOFTWARE na platformach komputerowych. |
uwsa-4b |
UNWANTED_SOFTWARE |
Ta lista zawiera zagrożenia typu UNWANTED_SOFTWARE na platformach Android. |
pha-4b |
POTENTIALLY_HARMFUL_APPLICATION |
Ta lista zawiera zagrożenia typu POTENTIALLY_HARMFUL_APPLICATION na platformach Android. |
Dodatkowe listy mogą być dostępne w późniejszym terminie. Wtedy ta tabela zostanie rozszerzona, a wyniki z metody hashList.list będą zawierać podobne wyniki z najnowszymi listami.
Aktualizacje bazy danych
Klient regularnie wywołuje metodę hashList.get lub hashLists.batchGet, aby aktualizować bazę danych. Ponieważ typowy klient chce zwykle aktualizować wiele list jednocześnie, zalecamy użycie metody hashLists.batchGet.
Nazwy list nigdy nie zostaną zmienione. Ponadto lista, która się pojawi, nigdy nie zostanie usunięta (jeśli nie będzie już przydatna, stanie się pusta, ale nadal będzie istnieć). Dlatego warto zakodować te nazwy w kodzie klienta Bezpiecznego przeglądania Google.
Zarówno metoda hashList.get, jak i metoda hashLists.batchGet obsługują aktualizacje przyrostowe. Korzystanie z aktualizacji przyrostowych pozwala oszczędzać przepustowość i zwiększać wydajność. Aktualizacje przyrostowe polegają na przesyłaniu różnicy między wersją listy klienta a jej najnowszą wersją. (jeśli klient został niedawno wdrożony i nie ma żadnych dostępnych wersji, dostępna jest pełna aktualizacja). Aktualizacja przyrostowa zawiera indeksy usunięcia i dodania. Najpierw klient musi usunąć z lokalnej bazy danych wpisy o określonych indeksach, a następnie zastosować zmiany.
Aby zapobiec uszkodzeniu, klient powinien sprawdzić zapisane dane pod kątem zgodności z sumą kontrolną podaną przez serwer. Jeśli suma kontrolna nie pasuje, klient powinien przeprowadzić pełną aktualizację.
Dekodowanie zawartości listy
Dekodowanie skrótów i prefiksów haszowych
Wszystkie listy są dostarczane przy użyciu specjalnego kodowania, aby zmniejszyć ich rozmiar. To kodowanie działa dzięki temu, że listy Bezpiecznego przeglądania Google zawierają teoretycznie zbiór hasz lub prefiksów hasz, które są statystycznie nie do odróżnienia od losowych liczb całkowitych. Gdybyśmy posortowali te liczby całkowite i obliczyli różnicę między sąsiednimi elementami, ta różnica byłaby w jakimś sensie „mała”. Kodowanie Golomb-Rice wykorzystuje tę niewielką wielkość.
Załóżmy, że 3 wyrażenia prefiksów ścieżki z sufiksem hosta, a mianowicie a.example.com/
, b.example.com/
i y.example.com/
, mają być przesyłane za pomocą 4-bajtowych prefiksów haszowanych. Załóżmy też, że parametr Rice’a, oznaczony jako k, ma wartość
- Serwer najpierw oblicza pełny ciąg znaków dla tych ciągów, które są odpowiednio:
291bc5421f1cd54d99afcc55d166e2b9fe42447025895bf09dd41b2110a687dc a.example.com/
1d32c5084a360e58f1b87109637a6810acad97a861a7769e8f1841410d2a960c b.example.com/
f7a502e56e8b01c6dc242b35122683c9d25d07fb1f532d9853eb0ef3ff334f03 y.example.com/
Następnie serwer tworzy 4-bajtowe prefiksy skrótu dla każdego z tych elementów. Są to pierwsze 4 bajty 32-bajtowego pełnego skrótu interpretowanego jako 32-bitowa liczba całkowita w systemie big-endian. Wielkiendianizm odnosi się do faktu, że pierwszy bajt pełnego hasha staje się najbardziej znaczącym bajtem 32-bitowej liczby całkowitej. W wyniku tego kroku otrzymasz liczby całkowite 0x291bc542, 0x1d32c508 i 0xf7a502e5.
Serwer musi posortować te 3 prefiksy haszowane według alfabetu (co jest równoznaczne z sortowaniem numerycznym w systemie big endian). Wynikiem takiego sortowania jest 0x1d32c508, 0x291bc542, 0xf7a502e5. Pierwszy prefiks haszowany jest przechowywany w polu first_value
bez zmian.
Następnie serwer oblicza 2 sąsiednie różnice, które wynoszą odpowiednio 0xbe9003a i 0xce893da3. Ponieważ k jest równe 30, serwer dzieli te 2 liczby na części iloraza i reszty, które mają odpowiednio 2 i 30 bitów. W przypadku pierwszego numeru część ilorazową jest 0, a pozostałość to 0xbe9003a; w przypadku drugiego numeru część ilorazową jest 3, ponieważ 2 najważniejsze bity w systemie dwójkowym to 11, a pozostałość to 0xe893da3. W przypadku danego ilorazu q
jest on kodowany w wartości (1 << q) - 1
za pomocą dokładnie 1 + q
bitów; reszta jest kodowana bezpośrednio za pomocą k bitów. Część iloraza pierwszego numeru jest zakodowana jako 0, a część reszty jest w formacie binarnym 001011111010010000000000111010; część iloraza drugiego numeru jest zakodowana jako 0111, a część reszty jest równa 001110100010010011110110100011.
Gdy te liczby zostaną utworzone w postaci ciągu bajtów, zostanie użyty format little-endian. Koncepcyjnie łatwiej sobie wyobrazić długi ciąg bitów tworzony od najmniej znaczących bitów: bierzemy część ilorazową pierwszego numeru i dołączamy do niego resztę pierwszego numeru; następnie dołączamy część ilorazową drugiego numeru i dołączamy resztę. Powinieneś otrzymać taką dużą liczbę (przerwy między wierszami i komentarze zostały dodane w celu ułatwienia zrozumienia):
001110100010010011110110100011 # Second number, remainder part
0111 # Second number, quotient part
001011111010010000000000111010 # First number, remainder part
0 # First number, quotient part
W jednym wierszu wyglądałoby to tak:
00111010001001001111011010001101110010111110100100000000001110100
Oczywiście liczba ta znacznie przekracza 8 bitów dostępnych w pojedynczym bajcie. Kodowanie little endian pobiera następnie 8 najmniej istotnych bitów tej liczby i wyprowadza je jako pierwszy bajt, który ma postać 01110100. Dla ułatwienia możemy podzielić powyższy ciąg bitów na grupy po 8 bitów, zaczynając od najmniej znaczących bitów:
0 01110100 01001001 11101101 00011011 10010111 11010010 00000000 01110100
Kodowanie little-endian pobiera każdy bajt z prawej strony i umieszcza go w ciągu bajtów:
01110100
00000000
11010010
10010111
00011011
11101101
01001001
01110100
00000000
Widać, że ponieważ nowe części są dodawane do dużej liczby po lewej stronie (czyli dodawane są kolejne znaczące bity), a kodowanie i dekodowanie odbywa się od prawej strony (czyli od najmniej znaczących bitów), kodowanie i dekodowanie może być wykonywane stopniowo.
W efekcie
additions_four_bytes {
first_value: 489866504
rice_parameter: 30
entries_count: 2
encoded_data: "t\000\322\227\033\355It\000"
}
Aby odkodować prefiksy skrótu, klient wykonuje opisane powyżej czynności w odwrotnej kolejności.
Dekodowanie indeksów usunięcia
Indeksy usuwania są kodowane tą samą metodą co powyżej, czyli za pomocą 32-bitowych liczb całkowitych.
Częstotliwość aktualizacji
Klient powinien sprawdzić wartość zwróconą przez serwer w polu minimum_wait_duration
i na jej podstawie zaplanować następną aktualizację bazy danych. Ta wartość może być równa 0 (pole minimum_wait_duration
jest całkowicie puste). W takim przypadku klient MUSI natychmiast wykonać kolejną aktualizację.