Overview

はじめに

注: このドキュメントは現在開発中です。近日中に機能改善が予定されています。

Google セーフ ブラウジング v5 は、Google セーフ ブラウジング v4 の進化版です。v5 での主な変更点は、データの更新速度と IP プライバシーです。さらに、API サーフェスは柔軟性と効率性を高め、肥大化を減らすために改善されました。さらに、Google セーフ ブラウジング v5 は、v4 から簡単に移行できるように設計されています。

現在、Google は v4 と v5 の両方を提供しており、どちらも本番環境対応とみなされます。v4 または v5 を使用できます。v4 のサポート終了日についてはまだ発表しておりません。終了した場合は、少なくとも 1 年前にお知らせいたします。このページでは、v5 について説明し、v4 から v5 への移行ガイドを示します。v4 の完全なドキュメントは引き続き入手できます

データの鮮度

Google セーフ ブラウジング v5(具体的には v4 Update API)から大幅に改善された点の一つは、データの更新速度とカバレッジです。この保護はクライアントが維持するローカル データベースに大きく依存するため、ローカル データベースの更新の遅延とサイズが保護を見逃す主な原因となります。v4 の場合、クライアントが最新バージョンの脅威リストを取得するまでに 20 ~ 50 分かかります。残念なことに、フィッシング攻撃は急速に拡散しています。2021 年現在、攻撃を配信するサイトの 60% は 10 分以内に展開されています。Google の分析によると、フィッシング対策が行われていないユーザーの約 25 ~ 30% は、このようなデータの未更新が原因です。また、デバイスによっては、Google セーフ ブラウジングの脅威リスト全体を管理できないため、リストの規模は拡大し続けています。

v5 では、リアルタイム保護と呼ばれる運用モードが導入されています。これにより、前述のデータ未更新の問題を回避できます。v4 では、クライアントはローカル データベースをダウンロードして維持し、ローカルにダウンロードした脅威リストに対してチェックを行い、部分的な接頭辞と一致する場合にハッシュ全体をダウンロードするように要求されます。v5 でも、クライアントは引き続き脅威リストのローカル データベースをダウンロードして維持する必要がありますが、クライアントには無害なサイトのリスト(グローバル キャッシュ)をダウンロードし、このグローバル キャッシュのローカル チェックとローカルの脅威リスト チェックの両方を実施する必要があります。最後に、脅威リストで接頭辞が一致していない場合、またはグローバル キャッシュに一致しない場合、完全なハッシュをダウンロードするように要求します。(クライアントが必要とするローカル処理の詳細については、下記の該当する手順をご覧ください)。これは、「デフォルトで許可」から「デフォルトでチェック」に移行したことを意味します。これは、ウェブ上での脅威の拡散が加速しているため、保護の強化につながります。つまり、このプロトコルは準リアルタイムの保護を提供することを目的としたプロトコルです。Google は、最新の Google セーフ ブラウジング データをクライアントに提供しています。

IP プライバシー

Google セーフ ブラウジング(v4 または v5)は、リクエストの処理中にユーザー ID に関連付けられた何も処理しません。送信された Cookie は無視されます。リクエストの発信元 IP アドレスは Google に認識されますが、Google が IP アドレスを使用するのは重要なネットワーキング ニーズ(レスポンスの送信など)と DoS 対策の目的に限られます。

v5 と同時に、Safe Browsing Oblivious HTTP Gateway API というコンパニオン API を導入します。この設定では、Oblivious HTTP を使用してエンドユーザーの IP アドレスを Google に対して非表示にします。これは、ユーザー リクエストの暗号化されたバージョンを、共謀していない第三者に処理して Google に転送するという仕組みです。つまり、サードパーティは IP アドレスにのみアクセスでき、Google はリクエストのコンテンツにのみアクセスできます。サードパーティは Oblivious HTTP Relay(Fastly が提供するこのサービスなど)を、Google は Oblivious HTTP Gateway を運用しています。これはオプションのコンパニオン API です。Google セーフ ブラウジングと併用すると、エンドユーザーの IP アドレスが Google に送信されなくなります。

適切な使用

使用の許可

Safe Browsing API は非営利目的でのみ使用します(つまり、「販売や収益を生み出すことを目的としたものではありません」)。商用目的でソリューションが必要な場合は、Web Risk をご覧ください。

料金

Google Safe Browsing API はすべて無料です。

割り当て

デベロッパーには、Safe Browsing API を有効にするとデフォルトの使用量の割り当てが割り当てられます。現在の割り当てと使用量は、Google Developer Console で確認できます。現在割り当てられている割り当てを超えることが予想される場合は、Play Console の割り当てインターフェースから追加の割り当てをリクエストできます。Google はこれらのリクエストを審査し、サービスの可用性がすべてのユーザーのニーズを満たせるようにするため、割り当ての増加をお申込みいただく際は、ご連絡させていただきます。

適切な URL

Google セーフ ブラウジングは、ブラウザのアドレスバーに表示される URL で動作するように設計されています。サブリソース(HTML ファイルによって参照される JavaScript や画像、JavaScript によって開始された WebSocket URL など)のチェックに使用することは想定されていません。このようなサブリソースの URL については、Google セーフ ブラウジングのチェックを行わないでください

URL へのアクセスによってリダイレクト(HTTP 301 など)が発生した場合は、リダイレクト先の URL を Google セーフ ブラウジングに照らしてチェックすることをおすすめします。クライアントサイドの URL 操作(History.pushState など)では、新しい URL が Google セーフ ブラウジングのチェックを受けることはありません

ユーザーへの警告

Google セーフ ブラウジングを使用して、特定のウェブページからのリスクについてユーザーに警告する場合は、次のガイドラインが適用されます。

このガイドラインは、ページが安全でないウェブリソースであることが 100% の確実性でわかっていないことを明確化し、警告から発生し得るリスクを特定するにすぎないことを明確にすることで、お客様と Google の双方を誤解から守ることを目的としています。

  • ユーザーに表示される警告で、問題のページが安全でないウェブリソースであるとユーザーに誤解を与えないようにする必要があります。特定されたページ、またはユーザーがもたらす可能性のあるリスクについて言及する場合は、「疑わしい、潜在的、可能性のある、可能性が高い」、「可能性は高い」などの用語を使用して警告を表示する必要があります。
  • この警告は、ユーザーがさまざまな脅威に関する Google の定義を確認して詳細を把握できるようにする必要があります。次のリンクをおすすめします。
  • セーフ ブラウジング サービスによってリスクが高いと判断されたページについて警告を表示する場合は、セーフ ブラウジング アドバイザリへのリンクとともに「Google が提供するアドバイザリ」という行を追加して、Google に帰属を表示する必要があります。他のソースに基づく警告も商品に表示される場合は、Google 以外のデータから得られる警告に Google の帰属情報を含めないでください。
  • プロダクトのドキュメントで、Google セーフ ブラウジングによる保護が完全なものではないことをユーザーに知らせる必要があります。偽陽性(危険なサイトとして危険と警告されているサイト)と偽陰性(危険のフラグが付けられていない安全なサイト)の両方の可能性があることをお客様に伝える必要があります。次の表現を使用することをおすすめします。

    Google は、安全でないウェブリソースについて、最も正確で最新の情報を提供するよう努めています。ただし、Google は、サイトの情報が包括的でエラーがないことを保証するものではありません。危険なサイトもあれば、安全なサイトが誤って特定される場合もあります。

運用モード

Google セーフ ブラウジング v5 では、クライアントは 3 つの動作モードから選択できます。

リアルタイム モード

クライアントが Google セーフ ブラウジング v5 をリアルタイム モードで使用することを選択した場合、クライアントは(i)ホスト サフィックス/パス プレフィックス URL 式の SHA256 ハッシュとしてフォーマットされた、良性の可能性があるサイトのグローバル キャッシュ、(ii)ホスト サフィックス/パス プレフィックス URL 式の SHA256 ハッシュ形式としてフォーマットされた脅威リストのセットをローカル データベースに保持します。大まかに言うと、クライアントが特定の URL をチェックしようとするたびに、グローバル キャッシュを使用してローカル チェックが実行されます。このチェックに合格すると、ローカルの脅威リストのチェックが実行されます。それ以外の場合、クライアントは以下のようにリアルタイム ハッシュ チェックを続行します。

クライアントは、ローカル データベースのほかにローカル キャッシュを保持します。このようなローカル キャッシュは、永続ストレージにある必要はなく、メモリ不足の場合にクリアできます。

この手順の詳細な仕様については、以下をご覧ください。

ローカルリスト モード

クライアントがこのモードで Google セーフ ブラウジング v5 を使用することを選択した場合、クライアントの動作は v5 の改善された API サーフェスを使用する点を除き、v4 Update API と同様です。クライアントは、ホスト・サフィックス/パス・プレフィックスの URL 式の SHA256 ハッシュ・プレフィックスとしてフォーマットされた、一連の脅威リストをローカル・データベースに保持します。クライアントが特定の URL をチェックしようとするたびに、ローカルの脅威リストを使用してチェックが実行されます。一致する場合にのみ、クライアントはサーバーに接続してチェックを続行します。

前述したように、クライアントは永続ストレージにある必要のないローカル キャッシュも保持します。

ストレージなしのリアルタイム モード

クライアントが Google セーフ ブラウジング v5 をストレージのないリアルタイム モードで使用することを選択した場合、クライアントは永続的なローカル データベースを維持する必要がありません。ただし、クライアントにはローカル キャッシュを維持することが求められます。このようなローカル キャッシュは、永続ストレージにある必要はなく、メモリ不足の場合にクリアできます。

クライアントが特定の URL をチェックしようとするたびに、クライアントは常にサーバーに接続してチェックを実行します。このモードは、v4 Lookup API のクライアントが実装するモードと類似しています。

リアルタイム モードと比較すると、このモードではより多くのネットワーク帯域幅を使用できますが、永続的なローカル状態を維持するのにクライアントが不便な場合は、このモードのほうが適している可能性があります。

URL の確認

このセクションでは、クライアントが URL をチェックする仕組みについて詳しく説明します。

URL の正規化

URL を確認する前に、クライアントは URL の正規化を行うことが求められます。

まずは、クライアントが URL を解析し、RFC 2396 に基づいて有効にしたとします。URL で国際化ドメイン名(IDN)が使用されている場合、クライアントは URL を ASCII の Punycode 表現に変換する必要があります。URL にはパス コンポーネントを含める必要があります。つまり、ドメインの後に少なくとも 1 つのスラッシュが必要です(http://google.com ではなく http://google.com/)。

まず、URL からタブ文字(0x09)、CR(0x0d)、LF(0x0a)文字を削除します。これらの文字のエスケープ シーケンス(%0a など)は削除しないでください。

次に、URL がフラグメントで終わっている場合は、そのフラグメントを削除します。たとえば、http://google.com/#fraghttp://google.com/ に短縮します。

3 番目に、パーセント エスケープがなくなるまで、URL のエスケープ処理をパーセントで繰り返します。(これにより、URL が無効になることがあります)。

ホスト名を正規化するには:

URL からホスト名を抽出し、次の操作を行います。

  1. 先頭と末尾のドットをすべて削除する。
  2. 連続するドットを 1 つのドットに置き換える。
  3. ホスト名を IPv4 アドレスとして解析できる場合は、4 つのドット区切りの 10 進数値に正規化します。クライアントは、8 進数、16 進数、4 個未満の要素など、正式な IP アドレス エンコードをすべて処理する必要があります。
  4. ホスト名を角かっこで囲まれた IPv6 アドレスとして解析できる場合は、コンポーネント内の不要な先頭のゼロを削除し、ダブルコロン構文を使用してゼロのコンポーネントを折りたたんで正規化します。たとえば、[2001:0db8:0000::1][2001:db8::1] に変換する必要があります。ホスト名が次の 2 つの特別な IPv6 アドレスタイプのいずれかの場合は、IPv4 に変換します。
    • IPv4 にマッピングされた IPv6 アドレス(例: [::ffff:1.2.3.4])。1.2.3.4 に変換する必要があります。
    • 既知のプレフィックス 64:ff9b::/96 を使用した NAT64 アドレス([64:ff9b::1.2.3.4] など)。1.2.3.4 に変換する必要があります。
  5. 文字列全体を小文字にする。

パスを正規化するには:

  1. /.// に置き換え、前のパス コンポーネントとともに /../ を削除することで、パス内のシーケンス /..//./ を解決します。
  2. 連続するスラッシュの実行は単一のスラッシュ文字に置き換えます。

これらのパスの正規化をクエリ パラメータに適用しないでください。

URL 内で、ASCII 32 以下、127 以上、# または % のすべての文字をパーセントでエスケープします。エスケープには大文字の 16 進数を使用する必要があります。

ホスト サフィックスのパス接頭辞の式

URL が正規化されたら、次のステップとしてサフィックス/プレフィックスの式を作成します。接尾辞/接頭辞の式は、それぞれホスト接尾辞(またはフルホスト)とパス接頭辞(またはフルパス)で構成されます。

クライアントは、可能なホスト サフィックスとパス プレフィックスの組み合わせを最大 30 種類作成できます。これらの組み合わせでは、URL のホストとパスのコンポーネントのみが使用されます。スキーム、ユーザー名、パスワード、ポートは破棄されます。URL にクエリ パラメータが含まれている場合は、少なくとも 1 つの組み合わせにフルパスとクエリ パラメータが含まれます。

ホストの場合、クライアントは最大で 5 つの異なる文字列を試行します。それらは次のとおりです。

  • ホスト名が IPv4 でも IPv6 でもリテラルでない場合、eTLD+1 ドメインから始まり、先頭に連続してコンポーネントを追加することで、最大 4 つのホスト名が生成されます。eTLD+1 の決定は、公開サフィックス リストに基づいて行う必要があります。たとえば、a.b.example.com と指定すると、eTLD+1 ドメインは example.com になり、ホストには 1 つの追加のホスト コンポーネント b.example.com が付加されます。
  • URL の正確なホスト名。上記の例では、a.b.example.com がチェックされます。

パスの場合、クライアントは最大で 6 つの異なる文字列を試行します。次のとおりです。

  • クエリ パラメータを含む URL の正確なパス。
  • クエリ パラメータなしの URL の正確なパス。
  • ルート(/)から始まり、末尾のスラッシュを含むパス コンポーネントが連続して追加される 4 つのパス。

次の例では、チェックの動作を示します。

URL http://a.b.com/1/2.html?param=1 の場合、クライアントは次の文字列の候補を試行します。

a.b.com/1/2.html?param=1
a.b.com/1/2.html
a.b.com/
a.b.com/1/
b.com/1/2.html?param=1
b.com/1/2.html
b.com/
b.com/1/

URL http://a.b.c.d.e.f.com/1.html の場合、クライアントは次の文字列の候補を試行します。

a.b.c.d.e.f.com/1.html
a.b.c.d.e.f.com/
c.d.e.f.com/1.html
c.d.e.f.com/
d.e.f.com/1.html
d.e.f.com/
e.f.com/1.html
e.f.com/
f.com/1.html
f.com/

(注: b.c.d.e.f.com はスキップします。最後の 5 つのホスト名コンポーネントと完全なホスト名のみが取得されるため)。

URL http://1.2.3.4/1/ の場合、クライアントは次の文字列の候補を試行します。

1.2.3.4/1/
1.2.3.4/

URL http://example.co.uk/1 の場合、クライアントは次の文字列の候補を試行します。

example.co.uk/1
example.co.uk/

ハッシュ化

Google セーフ ブラウジングは、ハッシュ関数として SHA256 のみを使用します。このハッシュ関数は、上記の式に適用する必要があります。

完全な 32 バイトのハッシュは、状況に応じて 4 バイト、8 バイト、または 16 バイトに切り捨てられます。

  • 現在、hashes.search メソッドを使用する場合、リクエスト内のハッシュは 4 バイトに切り詰められる必要があります。このリクエストで追加のバイトを送信すると、ユーザーのプライバシーが侵害されます。

  • hashList.get メソッドまたは hashLists.batchGet メソッドを使用してローカル データベースのリストをダウンロードする場合、サーバーから送信されたハッシュの長さは、リストの性質と、desired_hash_length パラメータで通知されるクライアントのハッシュ長の設定によって決まります。

リアルタイムでの URL チェックの手順

この手順は、クライアントがリアルタイム運用モードを選択した場合に使用されます。

このプロシージャは、単一の URL u を受け取り、SAFEUNSAFE、または UNSURE を返します。SAFE が返された場合、その URL は Google セーフ ブラウジングによって安全であると判断されます。UNSAFE が返された場合、その URL は Google セーフ ブラウジングによって安全でない可能性があるとみなされ、エンドユーザーに警告を表示する、受信したメッセージを迷惑メールフォルダに移動する、続行前にユーザーによる追加の確認を求めるなどの適切な措置を講じる必要があります。UNSURE が返された場合は、後で次のローカルチェック手順を使用する必要があります。

  1. expressions を、URL u によって生成されるサフィックス/プレフィックス式のリストとします。
  2. expressionHashes をリストとします。要素は expressions の各式の SHA256 ハッシュです。
  3. expressionHasheshash ごとに次の操作を行います。
    1. hash がグローバル キャッシュで見つかる場合は、UNSURE を返します。
  4. expressionHashPrefixes をリストとします。要素は expressionHashes の各ハッシュの最初の 4 バイトです。
  5. expressionHashPrefixesexpressionHashPrefix ごとに次の操作を行います。
    1. ローカル キャッシュで expressionHashPrefix を検索します。
    2. キャッシュ エントリが見つかった場合:
      1. 現在の時刻が有効期限よりも後かどうかを判断する。
      2. 大きい場合は、次のようにします。
        1. 見つかったキャッシュ エントリをローカル キャッシュから削除します。
        2. ループ再生を続ける。
      3. サイズが小さい場合は、次のようにします。
        1. この特定の expressionHashPrefixexpressionHashPrefixes から削除します。
        2. expressionHashes 内の対応するフルハッシュがキャッシュ エントリにあるかどうかを確認します。
        3. 見つかった場合は、UNSAFE を返します。
        4. 見つからなかった場合は、ループを続行します。
    3. キャッシュされたエントリが見つからない場合は、このループを続行します。
  6. RPC SearchHashes または REST メソッド hashes.search を使用して、Google セーフ ブラウジング v5 サーバーに expressionHashPrefixes を送信します。エラー(ネットワーク エラー、HTTP エラーなど)が発生した場合は、UNSURE を返します。それ以外の場合は、レスポンスを SB サーバーから受信した response とします。これは、完全なハッシュのリストと、脅威の性質(ソーシャル エンジニアリング、マルウェアなど)を識別する補助情報、キャッシュの有効期限 expiration です。
  7. responsefullHash ごとに次の操作を行います。
    1. fullHashexpiration とともにローカル キャッシュに挿入します。
  8. responsefullHash ごとに次の操作を行います。
    1. expressionHashesfullHash が見つかった結果を isFound とします。
    2. isFound が False の場合は、ループを続行します。
    3. isFound が True の場合は、UNSAFE を返します。
  9. SAFE を返します。

このプロトコルではクライアントが expressionHashPrefixes をサーバーに送信するタイミングを指定しますが、送信する具体的な方法は意図的には指定していません。たとえば、クライアントが 1 つのリクエストですべての expressionHashPrefixes を送信したり、クライアントが expressionHashPrefixes の個々の接頭辞を別々のリクエストでサーバーに送信したりすることもできます(おそらく並行して進めます)。また、1 回のリクエストで送信されるハッシュ接頭辞の数が 30 を超えない限り、クライアントが expressionHashPrefixes のハッシュ接頭辞とともに、無関係な、またはランダムに生成されたハッシュ接頭辞を送信することもできます。

LocalThreat リストの URL チェック手順

この手順は、クライアントがローカルリスト操作モードを選択した場合に使用されます。また、上記の RealTimeCheck プロシージャがクライアントが UNSURE の値を返す場合にも使用されます。

このプロシージャは、単一の URL u を受け取り、SAFE または UNSAFE を返します。

  1. expressions を、URL u によって生成されるサフィックス/プレフィックス式のリストとします。
  2. expressionHashes をリストとします。要素は expressions の各式の SHA256 ハッシュです。
  3. expressionHashPrefixes をリストとします。要素は expressionHashes の各ハッシュの最初の 4 バイトです。
  4. expressionHashPrefixesexpressionHashPrefix ごとに次の操作を行います。
    1. ローカル キャッシュで expressionHashPrefix を検索します。
    2. キャッシュ エントリが見つかった場合:
      1. 現在の時刻が有効期限よりも後かどうかを判断する。
      2. 大きい場合は、次のようにします。
        1. 見つかったキャッシュ エントリをローカル キャッシュから削除します。
        2. ループ再生を続ける。
      3. サイズが小さい場合は、次のようにします。
        1. この特定の expressionHashPrefixexpressionHashPrefixes から削除します。
        2. expressionHashes 内の対応するフルハッシュがキャッシュ エントリにあるかどうかを確認します。
        3. 見つかった場合は、UNSAFE を返します。
        4. 見つからなかった場合は、ループを続行します。
    3. キャッシュされたエントリが見つからない場合は、このループを続行します。
  5. expressionHashPrefixesexpressionHashPrefix ごとに次の操作を行います。
    1. ローカルの脅威リスト データベースで expressionHashPrefix を検索します。
    2. ローカルの脅威リスト データベースで expressionHashPrefix が見つからない場合は、expressionHashPrefixes から削除します。
  6. RPC SearchHashes または REST メソッド hashes.search を使用して、Google セーフ ブラウジング v5 サーバーに expressionHashPrefixes を送信します。エラー(ネットワーク エラー、HTTP エラーなど)が発生した場合は、SAFE を返します。それ以外の場合は、レスポンスを SB サーバーから受信した response とします。これは、完全なハッシュのリストと、脅威の性質(ソーシャル エンジニアリング、マルウェアなど)を識別する補助情報、キャッシュの有効期限 expiration です。
  7. responsefullHash ごとに次の操作を行います。
    1. fullHashexpiration とともにローカル キャッシュに挿入します。
  8. responsefullHash ごとに次の操作を行います。
    1. expressionHashesfullHash が見つかった結果を isFound とします。
    2. isFound が False の場合は、ループを続行します。
    3. isFound が True の場合は、UNSAFE を返します。
  9. SAFE を返します。

ローカル データベースを使用しないリアルタイム URL チェック手順

この手順は、クライアントがストレージなしのリアルタイム オペレーション モードを選択した場合に使用されます。

このプロシージャは、単一の URL u を受け取り、SAFE または UNSAFE を返します。

  1. expressions を、URL u によって生成されるサフィックス/プレフィックス式のリストとします。
  2. expressionHashes をリストとします。要素は expressions の各式の SHA256 ハッシュです。
  3. expressionHashPrefixes をリストとします。要素は expressionHashes の各ハッシュの最初の 4 バイトです。
  4. expressionHashPrefixesexpressionHashPrefix ごとに次の操作を行います。
    1. ローカル キャッシュで expressionHashPrefix を検索します。
    2. キャッシュ エントリが見つかった場合:
      1. 現在の時刻が有効期限よりも後かどうかを判断する。
      2. 大きい場合は、次のようにします。
        1. 見つかったキャッシュ エントリをローカル キャッシュから削除します。
        2. ループ再生を続ける。
      3. サイズが小さい場合は、次のようにします。
        1. この特定の expressionHashPrefixexpressionHashPrefixes から削除します。
        2. expressionHashes 内の対応するフルハッシュがキャッシュ エントリにあるかどうかを確認します。
        3. 見つかった場合は、UNSAFE を返します。
        4. 見つからなかった場合は、ループを続行します。
    3. キャッシュされたエントリが見つからない場合は、このループを続行します。
  5. RPC SearchHashes または REST メソッド hashes.search を使用して、Google セーフ ブラウジング v5 サーバーに expressionHashPrefixes を送信します。エラー(ネットワーク エラー、HTTP エラーなど)が発生した場合は、SAFE を返します。それ以外の場合は、レスポンスを SB サーバーから受信した response とします。これは、完全なハッシュのリストと、脅威の性質(ソーシャル エンジニアリング、マルウェアなど)を識別する補助情報、キャッシュの有効期限 expiration です。
  6. responsefullHash ごとに次の操作を行います。
    1. fullHashexpiration とともにローカル キャッシュに挿入します。
  7. responsefullHash ごとに次の操作を行います。
    1. expressionHashesfullHash が見つかった結果を isFound とします。
    2. isFound が False の場合は、ループを続行します。
    3. isFound が True の場合は、UNSAFE を返します。
  8. SAFE を返します。

リアルタイム URL チェック手順と同様に、この手順ではハッシュ プレフィックスをサーバーに送信する具体的な方法は指定しません。たとえば、クライアントが 1 つのリクエストですべての expressionHashPrefixes を送信したり、クライアントが expressionHashPrefixes の個々の接頭辞を別々のリクエストでサーバーに送信したりすることもできます(おそらく並行して進めます)。また、1 回のリクエストで送信されるハッシュ接頭辞の数が 30 を超えない限り、クライアントが expressionHashPrefixes のハッシュ接頭辞とともに、無関係な、またはランダムに生成されたハッシュ接頭辞を送信することもできます。

ローカル データベースのメンテナンス

Google セーフ ブラウジング v5 では、クライアントがローカル データベースを保持することを想定しています(クライアントが「ストレージなしリアルタイム モード」を選択している場合を除きます)。このローカル データベースの形式とストレージはクライアントによって異なります。このローカル データベースの内容は、概念的には、さまざまなリストをファイルとして含むフォルダと考えることができ、これらのファイルの内容は SHA256 ハッシュまたはハッシュ プレフィックスです。

データベースの更新

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

リストは個別の名前で識別されます。名前は、数文字の短い ASCII 文字列です。

V4 とは異なり、リストは脅威の種類、プラットフォーム タイプ、脅威エントリ タイプのタプルによって識別されますが、v5 のリストは単に名前によって識別されます。これにより、複数の v5 リストが同じ脅威タイプを共有する場合でも、柔軟に対応できます。プラットフォーム タイプと脅威エントリ タイプは v5 で削除されます。

リストの名前を一度指定すると、その名前が変更されることはありません。また、一度表示されたリストが削除されることはありません(リストが有用でなくなった場合は、空になりますが、そのリストは引き続き存在します)。そのため、これらの名前を Google セーフ ブラウジングのクライアント コードにハードコードすることをおすすめします。

hashList.get メソッドhashLists.batchGet メソッドはどちらも増分更新をサポートしています。増分アップデートを使用すると、帯域幅が節約され、パフォーマンスが向上します。増分アップデートは、クライアントのリストのバージョンとリストの最新バージョンの間の差分を送信することによって機能します。(クライアントが新たに導入され、利用可能なバージョンがない場合は、フル アップデートが利用可能です)。増分アップデートには削除インデックスと追加コンテンツが含まれています。クライアントはまず、指定されたインデックスにあるエントリをローカル データベースから削除してから、追加を適用します。

最後に、破損を防ぐため、クライアントはサーバーから提供されるチェックサムと照らし合わせて、格納されているデータを確認する必要があります。チェックサムが一致しない場合、クライアントはフル アップデートを実行する必要があります。

リスト内容のデコード

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

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

ホスト サフィックスのパス プレフィックス式 a.example.com/b.example.com/y.example.com/ の 3 つの式を、4 バイトのハッシュ プレフィックスを使用して送信するとします。さらに、Rice パラメータ(k)は 30 に選択されたとします。サーバーはまず、これらの文字列の完全なハッシュを計算します。

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 ビット長)に分割します。1 つ目の数値の商は 0、余りは 0xbe9003a です。2 つ目の数値の商は 3 になります。これは、上位 2 つのビットが 2 進数で 11、余りが 0xe893da3 であるためです。商 q に対して、正確に 1 + q ビットを使用して (1 << q) - 1 にエンコードされ、残りは k ビットを使用して直接エンコードされます。1 つ目の数値の商部分は 0 でエンコードされ、余りは 2 進数の 001011111010010000000000111010 となります。2 つ目の数値の商部分は 0111、余りは 00111010001011011 となります。

これらの数値がバイト文字列に生成される場合、リトル エンディアンが使用されます。概念的には、長いビット文字列が最下位ビットから始まることを想像しやすくなります。最初の数値の商部分を先頭にし、その商の余りを先頭に付加します。次に、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

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

最終的に、

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

クライアントは単純に上記の手順を逆に行い、ハッシュ接頭辞をデコードします。v4 とは異なり、ハッシュ接頭辞の整数はビッグ エンディアンとして解釈されるため、最後にバイトスワップを行う必要はありません。

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

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

使用可能なリスト

v5alpha1 での使用が推奨されるリストは次のとおりです。

リスト名 対応する v4 ThreatType 列挙型 説明
gc 一切届かない このリストはグローバル キャッシュのリストです。これは、リアルタイム オペレーション モードでのみ使用される特別なリストです。
se SOCIAL_ENGINEERING このリストには、SOCIAL_ENGINEERING 脅威タイプの脅威が含まれています。
mw MALWARE このリストには、デスクトップ・プラットフォームを対象とするマルウェアの脅威の種類が掲載されています。
uws UNWANTED_SOFTWARE このリストには、デスクトップ プラットフォーム向けの UNWANTED_SOFTWARE 脅威タイプに関する脅威が含まれています。
uwsa UNWANTED_SOFTWARE このリストには、Android プラットフォームに対する UNWANTED_SOFTWARE 脅威タイプに関する脅威が含まれています。
pha POTENTIALLY_HARMFUL_APPLICATION このリストには、Android プラットフォームに対する POTENTIALLY_HARMFUL_APPLICATION 脅威タイプによる脅威が含まれています。

他のリストは後日追加可能になり、その時点で上記の表を拡張します。

クライアントがキャッシュ プロキシ サーバーを動作させ、上記のリストの一部またはすべてを取得してから、クライアントがプロキシ サーバーに接続することが許可されます。これを実装する場合は、5 分などの短いキャッシュ期間を設定することをおすすめします。将来的には、このキャッシュ期間は標準の Cache-Control HTTP ヘッダーを使用して通知される可能性があります。

更新の頻度

クライアントは、サーバーの minimum_wait_duration フィールドで返された値を確認し、その値を使用してデータベースの次回の更新をスケジュールする必要があります。この値は 0 の可能性があり(フィールド minimum_wait_duration が完全に欠落している場合)、クライアントはすぐに別の更新を実行するべきです。

リクエストの例

このセクションでは、HTTP API を直接使用して Google セーフ ブラウジングにアクセスする例をいくつか紹介します。通常は、生成された言語バインディングを使用することをおすすめします。これは、エンコードとデコードを便利な方法で自動的に処理するためです。バインディングについては、ドキュメントをご覧ください。

hashes.search メソッドを使用した HTTP リクエストの例を次に示します。

GET https://safebrowsing.googleapis.com/v5/hashes:search?key=INSERT_YOUR_API_KEY_HERE&hashPrefixes=WwuJdQ

レスポンスの本文はプロトコル バッファ形式のペイロードで、デコードできます。

hashLists.batchGet メソッドを使用した HTTP リクエストの例を次に示します。

GET https://safebrowsing.googleapis.com/v5alpha1/hashLists:batchGet?key=INSERT_YOUR_API_KEY_HERE&names=se&names=mw

レスポンスの本文もプロトコル バッファ形式のペイロードで、デコードできます。

移行ガイド

現在 v4 Update API を使用している場合は、ローカル データベースをリセットまたは消去することなく、v4 から v5 にシームレスに移行できます。このセクションでは、その方法について説明します。

リストの更新の変換

v4 では、threatListUpdates.fetch メソッドを使用してリストをダウンロードします。v5 では、hashLists.batchGet メソッドに切り替えます。

リクエストを次のように変更してください。

  1. v4 ClientInfo オブジェクトを完全に削除します。専用のフィールドを使用してクライアントの ID を指定する代わりに、よく知られた User-Agent ヘッダーを使用するだけで済みます。このヘッダーにはクライアント ID を指定する決まった形式はありませんが、元のクライアント ID とクライアント バージョンをスペースまたはスラッシュで区切って指定することをおすすめします。
  2. v4 ListUpdateRequest オブジェクトごとに、次の操作を行います。
    • 上記の表で対応する v5 のリスト名を検索し、その名前を v5 のリクエストに指定します。
    • threat_entry_typeplatform_type などの不要なフィールドを削除します。
    • v4 の state フィールドは、v5 の versions フィールドと直接互換性があります。v4 では state フィールドを使用してサーバーに送信されるのと同じバイト文字列を、v5 でも versions フィールドを使用して簡単に送信できます。
    • v4 の制約については、v5 では SizeConstraints という簡素化されたバージョンが使用されます。region などの追加フィールドは削除する必要があります。

レスポンスを次のように変更する必要があります。

  1. v4 の enum ResponseType は、単に partial_update という名前のブール値フィールドに置き換えられます。
  2. minimum_wait_duration フィールドを 0 にすることも、省略することもできるようになりました。含まれている場合、クライアントはすぐに別のリクエストを行うよう要求されます。これは、クライアントが SizeConstraints で、最大更新サイズに対して、最大データベース サイズよりも小さい制約を指定した場合にのみ発生します。
  3. 32 ビット整数用の Rice デコード アルゴリズムを調整する必要があります。違いは、エンコードされたデータが別のエンディアンでエンコードされることです。v4 と v5 の両方で、32 ビットのハッシュ接頭辞は辞書順に並べ替えられます。しかし、v4 では、これらの接頭辞は並べ替え時にリトル エンディアンとして扱われ、v5 では並べ替え時にビッグ エンディアンとして扱われます。つまり、辞書順の並べ替えはビッグ エンディアンを使用する数値の並べ替えと同一であるため、クライアントは並べ替えを行う必要はありません。Chromium の v4 実装におけるこの種の例については、こちらをご覧ください。このような並べ替えは削除できます。
  4. 他のハッシュ長に対しては、Rice デコード アルゴリズムを実装する必要があります。

ハッシュ検索の変換

v4 では、fullHashes.find メソッドを使用してフルハッシュを取得します。V5 の同等のメソッドは hashes.search メソッドです。

リクエストを次のように変更してください。

  1. 長さがちょうど 4 バイトのハッシュ接頭辞のみを送信するようにコードを構造化します。
  2. v4 の ClientInfo オブジェクトを完全に削除します。専用のフィールドを使用してクライアントの ID を指定する代わりに、よく知られた User-Agent ヘッダーを使用するだけで済みます。このヘッダーにはクライアント ID を指定する決まった形式はありませんが、元のクライアント ID とクライアント バージョンをスペースまたはスラッシュで区切って指定することをおすすめします。
  3. client_states フィールドを削除します。不要になりました。
  4. threat_types などのフィールドを含める必要がなくなりました。

レスポンスを次のように変更する必要があります。

  1. minimum_wait_duration フィールドが削除されました。クライアントはいつでも新しいリクエストを発行できます。
  2. v4 の ThreatMatch オブジェクトは、FullHash オブジェクトに簡略化されました。
  3. キャッシュは、単一のキャッシュ期間に簡素化されました。キャッシュの操作については、上記の手順をご覧ください。