概要
クライアント署名により、リスク分析を改善するための追加情報をユーザーが reCAPTCHA に送信できます。情報は暗号化されるため、ユーザーや潜在的な攻撃者は、このデータの読み取りまたは改ざんができません。
ペイロード
ペイロードは、次のフィールドが含まれる JSON オブジェクトです。
ts_ms
: エポックからのミリ秒数。これは現在の時刻に設定します。リプレイ攻撃の防止に使用されます。数分前の ClientSignature が見つかった場合は、EXPIRED
を返します。UNIX エポックとも呼ばれます。session_id
: ソリューションを識別してこのセッションにバインドする一意の ID。ID ごとに有効にできる recaptcha ソリューションは 1 つだけです。string
として渡します。url_hash
: 完全な URL の 8 文字のハッシュ プレフィックス(スキーム/パス/パラメータを含む)。ua_hash
: ユーザー エージェントの 8 文字のハッシュ プレフィックス。callback_hash
: JavaScript コールバックの 10 文字のハッシュ プレフィックス(空白は削除)。コールバックがない場合は、コールバックを追加し、getResponse() や フォーム フィールドから読み取るのではなく、そのコールバックを使用してください。
たとえば、コールバックが次の場合:
function(response) {
document.location = "//example.com/recaptcha?session=ef969321&recaptcha=" + response;
}
ハッシュ化するテキストは次のようになります。
document.location="//example.com/recaptcha?session=ef969321&recaptcha="+response;
これにより、9B39FBB667
で始まるハッシュが生成されます。
ip
: エンドユーザーの IP アドレス。IPv4 または IPv6 を使用できます。
暗号化
AES-GCM でオブジェクトを暗号化する
- JSON オブジェクトをバイトに変換(UTF-8)します。
- reCAPTCHA 共有シークレットをハッシュ(SHA256)し、バイト(UTF-8)を取得して、暗号化鍵を準備します。
- 12 バイトの IV と 16 バイトの認証タグを使用し、最終結果の前に iv を追加して、JSON ペイロードを暗号化します。
- base64 としてエンコードされた iv +暗号化された blob を返します。
Python の例:
import base64
import hashlib
import json
import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
def GetEncryptedClientSignature(timestamp_ms, session_id):
iv = os.urandom(12)
aesgcm = AESGCM(hashlib.sha256(SHARED_SECRET.encode('utf-8')).digest())
signature = json.dumps({
'session_id': session_id,
'ts_ms': timestamp_ms
})
return base64.urlsafe_b64encode(
iv + aesgcm.encrypt(iv, signature.encode('utf-8'), None)).decode().rstrip('=')
Shared Secret
ペイロードの暗号化に使用される共有シークレットは、鍵のリソースのプロパティです。クライアント署名は試験運用版の機能であるため、共有シークレットは Cloud Console や gcloud CLI では表示されません。代わりに、REST API を使用する必要があります。共有シークレットは鍵ごとに保持されます。
リクエストのデータを使用する前に、次のように置き換えます。
- PROJECT_ID: 実際の Google Cloud プロジェクト ID
- KEY_NAME: 探索する鍵の名前
HTTP メソッドと URL:
GET https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/keys/key-name
リクエストを送信するには、次のいずれかのオプションを選択します。
curl
次のコマンドを実行します。
curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/keys/key-name"
PowerShell
次のコマンドを実行します。
$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }
Invoke-WebRequest `
-Method GET `
-Headers $headers `
-Uri "https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/keys/key-name" | Select-Object -Expand Content
次のような JSON レスポンスが返されます。
{ "name": "projects/PROJECT_ID/keys/KEY_NAME", "shared_secret": "6Ldqgs0UAAAAAIn4k7YxEB-LwEh5S9-Gv6IIWB8m" }
Hashes
ハッシュ プレフィックスは SHA256 HEX エンコード文字列である必要があります。完全なハッシュの代わりに接頭辞を送信できます。そうすると暗号化されたペイロードのサイズが小さくなります。8 バイト長の接頭辞を使用することをおすすめします。
Python の例:
import hashlib
import re
# Replace this with your JS function as it will show up in production.
f = """
function onSuccess(token) { a = token; form.submit(); }
"""
whitespace_pattern = re.compile(r'\s+');
function_pattern = re.compile(r'[^\{]*\{([\s\S]*)\};?$')
f = re.sub(whitespace_pattern, '', f)
f = re.search(function_pattern, f)
if not f:
print("function didn't seem like a function, did you include the {} ?")
else:
print(hashlib.sha256(f.groups()[0].encode('utf-8')).hexdigest())
配信
reCAPTCHA をリクエストする場合、インラインの場合は結果を data-s
として、明示的にレンダリングする場合は s
として含めます。
<div
data-sitekey="6LehsLkSAAAAAPF9gNzrbSN_vxQLgEFZW4-ZzSJa"
data-callback="onSuccess"
data-s="ZSYCxsDyhoYOSKBQkcFsx0N7b3XGSTanV0ESfgO5f5yxeklC29VWwSB8Wa1VZtkswPZCPCuxadxfHXRxXsdP4f5lL3knjxwAAYB1aydtt2Ae0KXo2tb10q72JKb0AxF_BXT4FUEj3URw4CAtFOTgSHoF_WhNY3yrjpm5KWmhl8pigfSv50Tv7h7WCYRA8cT3BsBzH3TZ">
</div>
次に execute() の使用例を示します。
grecaptcha.enterprise.execute(SITE_KEY, {action: "button", s: clientSignature}).then(
function(token) {
sendToBackendAndVerify(SITE_KEY, token);
});
検証
ClientSignature に関連する情報は、Assessment
の token_properties.client_signature
フィールドに返されます。
// Customers must confirm that this ID matches the ID they expect for the
// current event.
string session_id;
bool valid;
enum InvalidReason {
INVALID_REASON_UNSPECIFIED
INVALID_ENCRYPTION
INVALID_JSON
EXPIRED
}
// Errors in parsing or validating the ClientSignature. We share errors
// related to the signature through backend calls rather than client errors
// such as 400s because we want to limit the amount of information we share
// related to client signatures with possible attackers.
InvalidReason invalid_reason;
// Enum that represents a feature potentially useful for risk analysis.
enum Feature {
// Default unspecified type.
FEATURE_UNSPECIFIED;
// The IP provided in the signature does not match the IP address reCAPTCHA
// observed for this event. This can happen for legitimate reasons, so
// cautious should be exercised before taking action.
IP_MISMATCH;
// At least one feature of the environment does not match reCAPTCHA's point
// of view (URL, UserAgent, Callback). All of these environment features
// must be provided in the encrypted ClientSignature payload for this
// feature to be enabled.
UNEXPECTED_ENVIRONMENT;
}
// Features related to the signature which may be useful for risk analysis.
repeated Feature features;
テスト用に機能をトリガーする
いくつかの機能のトリガーを試して、統合をテストできます。
IP_MISMATCH
IP_MISMATCH
機能をトリガーするには、ip
フィールドにランダムな IP アドレスを指定します。テスト環境に応じて、IPv4 または IPv6 のアドレスを使用することが重要です。
UNEXPECTED_ENVIRONMENT
ua_hash
、url_hash
、および callback_hash
のすべてを指定する必要があります。この機能をトリガーするには、callback_hash
を ffffff
に変更してみてください。