Local Database
Zadbaj o dobrą organizację dzięki kolekcji
Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.
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ę.
O ile nie stwierdzono inaczej, treść tej strony jest objęta licencją Creative Commons – uznanie autorstwa 4.0, a fragmenty kodu są dostępne na licencji Apache 2.0. Szczegółowe informacje na ten temat zawierają zasady dotyczące witryny Google Developers. Java jest zastrzeżonym znakiem towarowym firmy Oracle i jej podmiotów stowarzyszonych.
Ostatnia aktualizacja: 2025-07-25 UTC.
[[["Łatwo zrozumieć","easyToUnderstand","thumb-up"],["Rozwiązało to mój problem","solvedMyProblem","thumb-up"],["Inne","otherUp","thumb-up"]],[["Brak potrzebnych mi informacji","missingTheInformationINeed","thumb-down"],["Zbyt skomplikowane / zbyt wiele czynności do wykonania","tooComplicatedTooManySteps","thumb-down"],["Nieaktualne treści","outOfDate","thumb-down"],["Problem z tłumaczeniem","translationIssue","thumb-down"],["Problem z przykładami/kodem","samplesCodeIssue","thumb-down"],["Inne","otherDown","thumb-down"]],["Ostatnia aktualizacja: 2025-07-25 UTC."],[],[],null,["# Local Database\n\nGoogle Safe Browsing v5 expects the client to maintain a local database, except when the client chooses the [No-Storage Real-Time Mode](/safe-browsing/reference#no-storage-real-time-mode). It is up to the client the format and storage of this local database. The contents of this local database can conceptually be thought of as a folder containing various lists as files, and the contents of these files are SHA256 hashes, or their corresponding prefixes with four byte hash prefix being the most commonly used hash length.\n\n### Available Lists\n\nLists are identified by their distinct names which follows a naming convention where the name contains a suffix that signifies the length of the hash you should expect in the list. Hash lists with the same threat type but different hash length will be a separately named list that's qualified with a suffix that indicates the hash length.\n\nThe following lists are available for use with the hash list methods.\n\n| List Name | Corresponding v4 `ThreatType` Enum | Description |\n|-----------|------------------------------------|------------------------------------------------------------------------------------------------------|\n| `gc-32b` | None | This list is a Global Cache list. It is a special list only used in the Real-Time mode of operation. |\n| `se-4b` | `SOCIAL_ENGINEERING` | This list contains threats of the SOCIAL_ENGINEERING threat type. |\n| `mw-4b` | `MALWARE` | This list contains threats of the MALWARE threat type for desktop platforms. |\n| `uws-4b` | `UNWANTED_SOFTWARE` | This list contains threats of the UNWANTED_SOFTWARE threat type for desktop platforms. |\n| `uwsa-4b` | `UNWANTED_SOFTWARE` | This list contains threats of the UNWANTED_SOFTWARE threat type for Android platforms. |\n| `pha-4b` | `POTENTIALLY_HARMFUL_APPLICATION` | This list contains threats of the POTENTIALLY_HARMFUL_APPLICATION threat type for Android platforms. |\n\nAdditional lists can become available at a later date, at which time the above table will be expanded, and the results from the [hashList.list method](/safe-browsing/reference/rest/v5/hashList/list) will show a similar result with the most up to date lists.\n\n### Database Updates\n\nThe client will regularly call the [hashList.get method](/safe-browsing/reference/rest/v5/hashList/get) or the [hashLists.batchGet method](/safe-browsing/reference/rest/v5/hashLists/batchGet) to update the database. Since the typical client will want to update multiple lists at a time, it is recommended to use [hashLists.batchGet method](/safe-browsing/reference/rest/v5/hashLists/batchGet).\n\nThe list names will never be renamed. Furthermore, once a list has appeared, it will never be removed (if the list is no longer useful, it will become empty but will continue to exist). Therefore, it is appropriate to hard code these names in the Google Safe Browsing client code.\n\nBoth the [hashList.get method](/safe-browsing/reference/rest/v5/hashList/get) and the [hashLists.batchGet method](/safe-browsing/reference/rest/v5/hashLists/batchGet) support incremental updates. Using incremental updates saves bandwidth and improves performance. Incremental updates work by delivering a delta between client's version of the list and the latest version of the list. (If a client is newly deployed and does not have any versions available, a full update is available.) The incremental update contains removal indices and additions. The client is first expected to remove the entries at the specified indices from its local database, and then apply the additions.\n\nFinally, to prevent corruption, the client should check the stored data against the checksum provided by the server. Whenever the checksum does not match, the client should perform a full update.\n\n### Decoding the List Content\n\n#### Decoding Hashes and Hash Prefixes\n\nAll lists are delivered using a special encoding to reduce size. This encoding works by recognizing that Google Safe Browsing lists contain, conceptually, a set of hashes or hash prefixes, which are statistically indistinguishable from random integers. If we were to sort these integers and take their adjacent difference, such adjacent difference is expected to be \"small\" in a sense. [Golomb-Rice encoding](https://en.wikipedia.org/wiki/Golomb_coding) then exploits this smallness.\n\nSuppose that three host-suffix path-prefix expressions, namely `a.example.com/`, `b.example.com/`, and `y.example.com/`, are to be transmitted using 4-byte hash prefixes. Further suppose that the Rice parameter, denoted by k, is chosen to be\n\n1. The server would start by calculating the full hash for these strings, which are, respectively:\n\n 291bc5421f1cd54d99afcc55d166e2b9fe42447025895bf09dd41b2110a687dc a.example.com/\n 1d32c5084a360e58f1b87109637a6810acad97a861a7769e8f1841410d2a960c b.example.com/\n f7a502e56e8b01c6dc242b35122683c9d25d07fb1f532d9853eb0ef3ff334f03 y.example.com/\n\nThe server then forms 4-byte hash prefixes for each of the above, which is the first 4 bytes of the 32-byte full hash, interpreted as big-endian 32-bit integers. The big endianness refers to the fact that the first byte of the full hash becomes the most significant byte of the 32-bit integer. This step results in the integers 0x291bc542, 0x1d32c508, and 0xf7a502e5.\n\nIt is necessary for the server to sort these three hash prefixes lexicographically (equivalent to numerical sorting in big endian), and the result of the sorting is 0x1d32c508, 0x291bc542, 0xf7a502e5. The first hash prefix is stored unchanged in the `first_value` field.\n\nThe server then calculates the two adjacent differences, which are 0xbe9003a and 0xce893da3 respectively. Given that k is chosen to be 30, the server splits these two numbers into the quotient parts and remainder parts that are 2 and 30 bits long respectively. For the first number, the quotient part is zero and the remainder is 0xbe9003a; for the second number, the quotient part is 3 because the most significant two bits are 11 in binary and the remainder is 0xe893da3. For a given quotient `q` it is encoded into `(1 \u003c\u003c q) - 1` using exactly `1 + q` bits; the remainder is encoded directly using k bits. The quotient part of the first number is encoded as 0, and the remainder part is in binary 001011111010010000000000111010; the quotient part of the second number is encoded as 0111, and the remainder part is 001110100010010011110110100011.\n\nWhen these numbers are formed into a byte string, little endian is used. Conceptually it may be easier to imagine a long bitstring being formed starting from the least significant bits: we take the quotient part of the first number and prepend the remainder part of the first number; we then further prepend the quotient part of the second number and prepend the remainder part. This should result in the following large number (linebreaks and comments added for clarity): \n\n 001110100010010011110110100011 # Second number, remainder part\n 0111 # Second number, quotient part\n 001011111010010000000000111010 # First number, remainder part\n 0 # First number, quotient part\n\nWritten in a single line this would be \n\n 00111010001001001111011010001101110010111110100100000000001110100\n\nObviously this number far exceeds the 8 bits available in a single byte. The little endian encoding then takes the least significant 8 bits in that number, and outputs it as the first byte which is 01110100. For clarity, we can group the above bitstring into groups of eight starting from the least significant bits: \n\n 0 01110100 01001001 11101101 00011011 10010111 11010010 00000000 01110100\n\nThe little endian encoding then takes each byte from the right and puts that into a bytestring: \n\n 01110100\n 00000000\n 11010010\n 10010111\n 00011011\n 11101101\n 01001001\n 01110100\n 00000000\n\nIt can be seen that since we conceptually *prepend* new parts to the large number on the left (i.e. adding more significant bits) but we encode from the right (i.e. the least significant bits), the encoding and decoding can be performed incrementally.\n\nThis finally results in \n\n additions_four_bytes {\n first_value: 489866504\n rice_parameter: 30\n entries_count: 2\n encoded_data: \"t\\000\\322\\227\\033\\355It\\000\"\n }\n\nThe client simply follows the above steps in reverse to decode the hash prefixes.\n\n#### Decoding Removal Indices\n\nRemoval indices are encoded using the exact same technique as above using 32-bit integers.\n\n### Update Frequency\n\nThe client should inspect the server's returned value in the field `minimum_wait_duration` and use that to schedule the next update of the database. This value is possibly zero (the field `minimum_wait_duration` is completely missing), in which case the client SHOULD immediately perform another update."]]