Local Database

Google セーフ ブラウジング v5 では、クライアントがローカル データベースを維持することが想定されています(クライアントがストレージなしのリアルタイム モードを選択した場合を除きます)。このローカル データベースの形式と保存は、クライアントに任されています。このローカル データベースの内容は、さまざまなリストがファイルとして格納されているフォルダと概念的に考えることができます。これらのファイルの内容は SHA256 ハッシュ、またはそれに相当するプレフィックスです。最も一般的なハッシュ長は 4 バイトのハッシュ プレフィックスです。

使用可能なリスト

リストは、命名規則に従った一意の名前で識別されます。この名前には、リストに含まれるハッシュの長さを示す接尾辞が含まれています。脅威の種類は同じでハッシュの長さが異なるハッシュリストは、別の名前のリストとして、ハッシュの長さを示す接尾辞で修飾されます。

ハッシュリスト メソッドで使用できるリストは次のとおりです。

リスト名 対応する v4 ThreatType 列挙型 説明
gc-32b なし このリストはグローバル キャッシュ リストです。これは、リアルタイム モードの動作でのみ使用される特別なリストです。
se-4b SOCIAL_ENGINEERING このリストには、SOCIAL_ENGINEERING 脅威タイプの脅威が含まれています。
mw-4b MALWARE このリストには、デスクトップ プラットフォームのマルウェア脅威の種類の脅威が含まれています。
uws-4b UNWANTED_SOFTWARE このリストには、パソコン プラットフォームの UNWANTED_SOFTWARE 脅威タイプの脅威が含まれています。
uwsa-4b UNWANTED_SOFTWARE このリストには、Android プラットフォームの UNWANTED_SOFTWARE 脅威タイプの脅威が含まれています。
pha-4b POTENTIALLY_HARMFUL_APPLICATION このリストには、Android プラットフォームの POTENTIALLY_HARMFUL_APPLICATION 脅威タイプの脅威が含まれています。

今後、追加のリストが利用可能になり、上記の表が拡張される予定です。hashList.list メソッドの結果は、最新のリストと同様の結果になります。

データベースの更新

クライアントは、hashList.get メソッドまたは hashLists.batchGet メソッドを定期的に呼び出してデータベースを更新します。通常のクライアントは一度に複数のリストを更新する必要があるため、hashLists.batchGet メソッドを使用することをおすすめします。

リスト名は変更されません。また、一度表示されたリストは削除されません(リストが役に立たなくなった場合は空になりますが、存在し続けます)。したがって、これらの名前は Google セーフ ブラウジング クライアント コードにハードコードするのが適切です。

hashList.get メソッドhashLists.batchGet メソッドの両方が、増分更新をサポートしています。増分更新を使用すると、帯域幅を節約し、パフォーマンスを向上させることができます。増分更新は、クライアントのリスト バージョンと最新バージョンのリストとの差分を配信することで機能します。(クライアントが新しくデプロイされ、利用可能なバージョンがない場合は、完全なアップデートが可能です)。増分更新には、削除インデックスと追加インデックスが含まれています。クライアントは、まず指定されたインデックスのエントリをローカル データベースから削除してから、追加を適用する必要があります。

最後に、破損を防ぐため、クライアントは保存されたデータをサーバーから提供されたチェックサムと照合する必要があります。チェックサムが一致しない場合、クライアントは完全な更新を実行する必要があります。

リスト コンテンツのデコード

ハッシュとハッシュ プレフィックスのデコード

すべてのリストは、サイズを小さくするために特別なエンコードを使用して配信されます。このエンコードは、Google Safe Browsing リストに、概念的には、ランダムな整数と統計的に区別できない一連のハッシュまたはハッシュ接頭辞が含まれていることを認識することで機能します。これらの整数を並べ替えて隣接する差を取ると、その差は「小さい」と見なされます。Golomb-Rice エンコードでは、この小ささを利用します。

4 バイトのハッシュ プレフィックスを使用して、3 つのホスト接尾辞パス プレフィックス式(a.example.com/b.example.com/y.example.com/)を送信するとします。さらに、Rice パラメータ(k で表記)が次のように選択されているとします。

  1. サーバーは、まずこれらの文字列の完全なハッシュを計算します。これらの文字列はそれぞれ次のとおりです。
291bc5421f1cd54d99afcc55d166e2b9fe42447025895bf09dd41b2110a687dc  a.example.com/
1d32c5084a360e58f1b87109637a6810acad97a861a7769e8f1841410d2a960c  b.example.com/
f7a502e56e8b01c6dc242b35122683c9d25d07fb1f532d9853eb0ef3ff334f03  y.example.com/

サーバーは、上記の各項目に 4 バイトのハッシュ プレフィックスを形成します。これは、32 バイトの完全なハッシュの最初の 4 バイトであり、ビッグ エンディアン 32 ビット整数として解釈されます。ビッグエンディアンとは、完全なハッシュの最初のバイトが 32 ビット整数の最上位バイトになることを意味します。このステップの結果、整数 0x291bc542、0x1d32c508、0xf7a502e5 が生成されます。

サーバーは、これらの 3 つのハッシュ接頭辞を辞書順に並べ替える必要があります(ビッグ エンディアンでの数値並べ替えと同等)。並べ替えの結果は 0x1d32c508、0x291bc542、0xf7a502e5 です。最初のハッシュ接頭辞は、first_value フィールドに変更なく保存されます。

サーバーは、2 つの隣接する差分(0xbe9003a と 0xce893da3)を計算します。k が 30 に選択されている場合、サーバーはこれらの 2 つの数値を、それぞれ 2 ビット長と 30 ビット長の商と剰余に分割します。最初の数値の場合、商は 0、余りは 0xbe9003a です。2 番目の数値の場合、商は 3 です。これは、上位 2 ビットがバイナリで 11 であり、余りが 0xe893da3 であるためです。特定の商 q は、正確に 1 + q ビットを使用して (1 << q) - 1 にエンコードされます。残りは k ビットを使用して直接エンコードされます。1 つ目の数値の商は 0 としてエンコードされ、余りはバイナリで 001011111010010000000000111010 です。2 つ目の数値の商は 0111 としてエンコードされ、余りは 001110100010010011110110100011 です。

これらの数値がバイト文字列に形成される場合、リトル エンディアンが使用されます。概念的には、最下位ビットから長いビット文字列が形成されていると想像するのが簡単です。最初の数値の商の部分を取り、最初の数値の剰余の部分を先頭に追加します。次に、2 番目の数値の商の部分を先頭に追加し、剰余の部分を先頭に追加します。すると、次の大きな数値が得られます(わかりやすくするために改行とコメントを追加しています)。

001110100010010011110110100011 # Second number, remainder part
0111 # Second number, quotient part
001011111010010000000000111010 # First number, remainder part
0 # First number, quotient part

1 行で記述すると次のようになります。

00111010001001001111011010001101110010111110100100000000001110100

この数は、1 バイトで使用できる 8 ビットをはるかに超えています。リトル エンディアン エンコードでは、その数値の最下位 8 ビットを取得し、最初のバイト(01110100)として出力します。わかりやすくするために、上記のビット文字列を最下位ビットから 8 個ずつグループ化できます。

0 01110100 01001001 11101101 00011011 10010111 11010010 00000000 01110100

リトルエンディアン エンコードでは、右から各バイトを取り出してバイト文字列に格納します。

01110100
00000000
11010010
10010111
00011011
11101101
01001001
01110100
00000000

概念的には、左側の大きな数値に新しい部分を先頭に追加(つまり、上位ビットを追加)しますが、右側(つまり下位ビット)からエンコードするため、エンコードとデコードを段階的に行うことができます。

最終的に、

additions_four_bytes {
  first_value: 489866504
  rice_parameter: 30
  entries_count: 2
  encoded_data: "t\000\322\227\033\355It\000"
}

クライアントは、上記の手順を逆に行うだけでハッシュ接頭辞をデコードできます。

削除インデックスのデコード

削除インデックスは、32 ビットの整数を使用して上記とまったく同じ手法でエンコードされます。

更新の頻度

クライアントは、フィールド minimum_wait_duration でサーバーが返した値を調べ、その値を使用してデータベースの次の更新をスケジュールする必要があります。この値はゼロの場合があり(フィールド minimum_wait_duration が完全に欠落している場合)、その場合はクライアントは直ちに別の更新を実行する必要があります。