CRYTIFY API

开发者文档

Crytify 提供两个核心接口:用于获取原始网络上下文的 IP 情报接口,以及返回 ALLOW、CHALLENGE 或 BLOCK 决策的请求信任接口。

第一次来这里?

手把手指南——从注册到上线

涵盖每个平台的完整流程(PHP、WordPress、Python、Node.js)。

打开指南 →

快速开始

  1. https://crytify.com/register 创建账户并打开控制台。
  2. 进入 Dashboard > Integration 创建一个 API key。
  3. 打开 Dashboard > Protection,选择 Easy、Medium 或 Hard。
  4. 下载 crytify.php,并在渲染受保护页面之前引入它。
  5. 让 Crytify 处理 ALLOW、BLOCK 以及托管 CHALLENGE 的跳转。

单文件 PHP 安装

只需一次 require 即可保护任意 PHP 页面。

下载 Crytify 提供的即插即用文件,放在受保护页面旁边,然后在任何 HTML 输出之前调用 crytify_gate()。

下载 crytify.php

1. 下载

curl -o crytify.php "https://crytify.com/download/crytify.php"

2. 添加到 index.php

<?php
require_once __DIR__ . '/crytify.php';

crytify_gate('cry_live_xxxxxxxxxxxx');

// Your existing page starts here.
?>
如果 Crytify 返回 CHALLENGE,该文件会自动将访客重定向到 Crytify 托管的验证页面。验证完成后,访客返回原页面,文件会把验证令牌发回给 Crytify。在生产环境中,你可以省略 key 参数,改为在服务器环境变量中设置 CRYTIFY_API_KEY。

可选

从 $_SESSION 读取访客数据。

crytify_gate() 已经自动把访客的网络与设备数据存入 $_SESSION['crytify']——无需额外调用。如果你更想直接读取像 $_SESSION['country'] 这样的扁平变量,可以在 crytify_gate() 之后的任意位置调用一次 crytify_populate_session()。这是刻意设计为选择性开启的:这些扁平字段使用了常见名称(country、city、timezone 等),可能与你应用中已有的会话变量冲突,所以除非你主动要求,否则不会写入任何内容。

用法

<?php
session_start();
require_once __DIR__ . '/crytify.php';
crytify_gate('cry_live_xxxxxxxxxxxx');
crytify_populate_session(); // optional

echo $_SESSION['country'];       // "Indonesia"
echo $_SESSION['isp'];           // "PT. Cyberindo Aditama"
echo $_SESSION['browser_name'];  // "Chrome"
?>

可用字段

asnisp organizationcountry countryCodecontinent regioncity timezoneutcOffset latlon browser_namebrowser_version os_nameos_version getDeviceNamegetBrandName getModeldetailsdevice

可选

用 on_result 记录每一个访客。

crytify_populate_session() 只在 ALLOW 时填充 $_SESSION——CHALLENGE 或 BLOCK 会渲染各自的页面并立即退出,所以你写在 crytify_gate() 之后的任何代码都不会对这些访客执行。如果你想记录每一次尝试——而不只是通过的那些——可以在选项数组中传入 on_result 回调。它会在三种决策下都执行,就在验证/拦截页面显示之前(或者在 ALLOW 时页面正常渲染之前)。

用法

<?php
require_once __DIR__ . '/crytify.php';

crytify_gate('cry_live_xxxxxxxxxxxx', [
    'on_result' => function (
        string $decision,
        array $network,
        array $device
    ) {
        $line = date('Y-m-d H:i:s') . " | {$decision} | "
            . ($network['country'] ?? '-') . ' | '
            . ($network['isp'] ?? '-') . ' | '
            . ($device['browser_name'] ?? '-') . "\n";
        file_put_contents(
            __DIR__ . '/visitors.txt',
            $line,
            FILE_APPEND | LOCK_EX
        );
    },
]);
?>

说明

  • 调用参数为 ($decision, $network, $device, $result)——结构与 $_SESSION['crytify'] 相同,另外第 4 个参数是原始 API 响应。
  • 仍处于 30 分钟通行 cookie 宽限期内的访客会完全跳过 API 调用,因此 on_result 不会为这些请求触发——没有新内容需要记录,访客身份与上次相同。
  • 如果你的回调抛出异常,会被捕获并忽略——日志记录的 bug 永远不会阻塞或破坏对真实访客的实际拦截逻辑。

节省额度

用 crytify_require_pass() 免费保护额外页面。

每次完整的 crytify_gate() 调用都会消耗额度,因为它会运行真正的检测流程。如果你的站点有一个明确的"前门"页面——比如落地页、登录页、产品页——真实访客在到达其他受保护页面(结账、账户、会员区)之前总会先经过它,那你就不需要在每一个页面上都重新运行完整检查。crytify_gate() 在 ALLOW 之后已经会设置一个带签名的 _crytify_pass cookie,有效期 30 分钟。crytify_require_pass() 是给这些其他页面用的轻量级、零额度检查:它只读取那个 cookie——没有 API 调用,没有检测流程,不产生费用。

如果 cookie 缺失或已过期(访客完全跳过了前门页面——这是常见的机器人/爬虫特征,因为真实浏览是通过点击路径到达的,而不是冷启动的直接命中),访客会被重定向到你指定的入口页面,并带上一个返回参数,这样他们在那里通过真正的检查后会直接回到原始页面。这一过程仍会出现在 Live Traffic 中(作为一条轻量日志事件,而非完整的信任决策),所以这个模式并非不可见——只是永远不会消耗额度。

入口页面(正常检查)

<?php
require_once __DIR__ . '/crytify.php';
crytify_gate('cry_live_xxxxxxxxxxxx');

// Page renders normally. On ALLOW, the
// _crytify_pass cookie is set automatically.
?>

其他受保护页面(免费)

<?php
require_once __DIR__ . '/crytify.php';
crytify_require_pass(
    'cry_live_xxxxxxxxxxxx',
    'https://yoursite.com/entry.php'
);

// Reached only if the cookie was valid —
// zero credits charged either way.
?>
仅在真实访客于正常使用中总是在你的入口页面之后才会到达的页面上使用此方法。如果某个页面在合理情况下可能是用户到达的第一个页面(来自广告、书签、未曾访问过就分享的链接),那里仍应使用完整的 crytify_gate()——否则每一次这样合理的直接访问都会被多绕一次重定向。

自定义验证页

从控制台为托管验证页添加品牌样式。

在 Dashboard > Protection 中,如果你希望验证页面匹配客户品牌,选择 Custom HTML。Crytify 仍然掌控令牌、CSRF、过期时间、提交动作与跳转流程。

必需的占位符

{{challenge_action}} 必需的表单提交地址。
{{csrf_field}} 必需的隐藏 CSRF 字段。
{{challenge_submit_button}} 必需的安全"继续"按钮。
{{challenge_message}} 建议展示给访客的提示信息。
{{challenge_error}} 建议展示的错误信息。

最小可用 HTML

<div class="challenge-box">
  <h1>Verify before continuing</h1>
  <p>{{challenge_message}}</p>
  {{challenge_error}}
  <form method="post" action="{{challenge_action}}">
    {{csrf_field}}
    {{challenge_submit_button}}
  </form>
</div>
POST /v1/ip

IP 情报

返回标准化的网络情报。此接口永远不会返回 ALLOW、CHALLENGE 或 BLOCK。

{
  "ip": "8.8.8.8"
}
POST /v1/trust

Trust Decision

评估请求上下文,同步返回信任决策,并附带宽泛的公开原因分类。

{
  "ip": "203.0.113.5",
  "method": "POST",
  "path": "/login",
  "mode": "medium",
  "headers": {
    "user-agent": "Mozilla/5.0 ...",
    "accept": "text/html"
  }
}

身份验证

每个请求都要带上你的 API key。无效或未授权的 key 永远不会被计费。

额度

IP lookup 消耗 1 点额度。Trust decision 依据 easy、medium 或 hard 模式消耗 2、4 或 8 点额度。

脱敏处理

Cookie、authorization、token、密钥、密码等敏感请求头不会被原样存储。

错误症状索引

Middleware 与预渲染安全问题修复

开发者经常搜索原始的 middleware 报错、状态码和预渲染相关症状。这些说明把常见的基础设施症状映射到安全的请求信任处理模式。

Next.js middleware timeout before render

Middleware waits on a remote trust check and the protected route renders slowly or times out.

Move the trust call to a fast server-side gate, enforce a short timeout, and fail open or fail closed based on page sensitivity. Crytify returns a compact ALLOW, CHALLENGE, or BLOCK decision for pre-render enforcement.

  1. Read the client IP and sanitized request headers in middleware or route handler code.
  2. Call POST /v1/trust with the route path and selected protection mode.
  3. Use a short timeout and return a local fallback when the network is unavailable.
  4. Apply the decision before rendering protected content.

403 Forbidden pre-render bypass

A route returns 403 inconsistently, or protected content flashes before the challenge decision is applied.

Run the trust decision before the page body is generated. For client-side gates, hide protected content until the server confirms ALLOW or CHALLENGE.

  1. Move trust enforcement before HTML generation or initial content reveal.
  2. Avoid relying on client-only checks for sensitive pages.
  3. Return BLOCK as 403, CHALLENGE as a verification step, and ALLOW as normal rendering.
  4. Log the request ID for dashboard investigation.

Express rate limit false positive login

Legitimate users are blocked because IP-only rate limits treat shared networks as one actor.

Combine rate limits with a request trust decision instead of blocking solely by IP count. Crytify adds context and returns a decision your app can enforce.

  1. Keep coarse rate limits for obvious floods.
  2. Send high-risk login attempts to /v1/trust with medium or hard mode.
  3. Challenge uncertain requests instead of blocking every shared-network user.
  4. Review broad reason categories in the dashboard.

Cloudflare Worker fetch timeout auth gate

An edge worker fetches an external API and delays authentication or checkout routes.

Use a small request body, colocate the trust call near the edge where possible, and enforce a strict timeout strategy. Crytify responses are compact for edge middleware.

  1. Send only required request context to /v1/trust.
  2. Use AbortController to cap latency.
  3. Cache static assets separately from protected routes.
  4. Fail according to endpoint sensitivity when the trust API is unavailable.

Laravel middleware returns 419 or 403 during bot protection

Security middleware conflicts with CSRF/session handling or blocks before the app can render an error page.

Separate CSRF/session errors from request trust decisions. Run Crytify as a pre-render gate and map ALLOW, CHALLENGE, and BLOCK to predictable app responses.

  1. Validate session and CSRF separately from trust checks.
  2. Call /v1/trust only after the request is structurally valid.
  3. Return a verification page for CHALLENGE and 403 for BLOCK.
  4. Do not expose internal evidence details in public errors.

nginx auth_request 403 loop

A reverse proxy or auth subrequest repeatedly redirects or returns 403 for protected paths.

Keep the edge auth decision stateless, exempt the challenge route from the protected location, and pass only normalized context to the trust API.

  1. Exclude challenge and static asset routes from the protected gate.
  2. Forward normalized IP and path metadata to the application gate.
  3. Apply Crytify decisions once per protected request.
  4. Record the request ID for debugging.

Base URL

https://api.crytify.com

身份验证

每个 API 请求都使用 Bearer token 格式携带你的 API key。无论 HTTP 方法是什么都是同样的方式——/v1/ip 和 /v1/trust 是 POST,而 /v1/usage 和 /v1/me 是 GET。

curl -X POST "https://api.crytify.com/v1/trust" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer cry_live_xxxxxxxxxxxx" \
  -d '{ ... }'

IP Lookup

当你只需要网络情报时使用 /v1/ip。消耗 1 点额度,不返回信任决策。

curl -X POST "https://api.crytify.com/v1/ip" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer cry_live_xxxxxxxxxxxx" \
  -d '{
    "ip": "8.8.8.8"
  }'
{
  "request_id": "req_123",
  "ip": "8.8.8.8",
  "network": {
    "country": "US",
    "network_type": "business"
  },
  "credits": {
    "charged": 1,
    "remaining_today": 999
  }
}

BIN Lookup

免费 · 无需 API key

根据任意支付卡的前 6–8 位数字(BIN/IIN)查询卡组织、类型、发卡行和国家。无需身份验证——限制为每个 IP 每分钟 10 次请求。

curl "https://api.crytify.com/api/bin/453201"
{
  "bin": "453201",
  "scheme": "Visa",
  "type": "Debit",
  "brand": "Visa Classic",
  "prepaid": false,
  "bank": {
    "name": "Jyske Bank",
    "city": "Silkeborg",
    "phone": "+4589893300"
  },
  "country": {
    "name": "Denmark",
    "code": "DK",
    "emoji": "🇩🇰",
    "currency": "DKK"
  }
}
字段说明
bin 你查询的 BIN(6–8 位数字)。
scheme 卡组织:Visa、Mastercard、Amex 等。
type Credit、Debit 或 Prepaid。
brand 子品牌(例如 Visa Classic、Mastercard Gold)。
prepaid 如果是预付卡则为 true。
bank.name 发卡银行名称。
country.code ISO 3166-1 alpha-2 国家代码。
country.currency ISO 4217 货币代码。

如果数据库中没有该 BIN 则返回 HTTP 404。超出速率限制时返回 HTTP 429——请退避后于 60 秒后重试。

Trust Decision

在渲染受保护内容之前使用 /v1/trust。传入 IP、方法、路径以及脱敏后的浏览器请求头。也可以选择性地附带来自 JavaScript SDK 的 fingerprint 对象,以提升请求一致性分析的准确度。 ↳ JavaScript SDK

curl -X POST "https://api.crytify.com/v1/trust" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer cry_live_xxxxxxxxxxxx" \
  -d '{
    "ip": "203.0.113.5",
    "mode": "hard",
    "method": "POST",
    "path": "/login",
    "url": "https://app.example.com/login",
    "challenge_return_url": "https://app.example.com/login",
    "headers": {
      "user-agent": "Mozilla/5.0 ...",
      "accept": "text/html,application/xhtml+xml",
      "accept-language": "en-US,en;q=0.9",
      "sec-ch-ua-platform": "\"Windows\""
    },
    "fingerprint": {
      "client_context": "generated by the Crytify JavaScript SDK"
    }
  }'
{
  "request_id": "req_456",
  "decision": "CHALLENGE",
  "mode": "hard",
  "trust_score": 42,
  "risk_score": 61,
  "reasons": [
    "identity_risk"
  ],
  "challenge": {
    "type": "hosted",
    "url": "https://crytify.com/challenge/abc123",
    "expires_in": 600,
    "token_param": "crytify_challenge_token"
  },
  "network": {
    "country": "US",
    "network_type": "unknown"
  },
  "credits": {
    "charged": 8,
    "remaining_today": 992
  }
}

托管验证流程

当决策为 CHALLENGE 时,将访客重定向到 challenge.url。验证完成后,Crytify 会带着 crytify_challenge_token 跳转回 challenge_return_url。请在下一次 /v1/trust 调用中将该值作为 challenge_token 发送。

测试模式

在探索接入流程时,可以在请求体中加入 "test": true。真实的决策引擎仍然照常运行——返回与生产环境相同的 ALLOW/CHALLENGE/BLOCK——但该请求的任何内容都不会写入 Crytify 的自学习数据(IP、ASN 或指纹信誉)。额度依然照常扣除,并且该请求会在你的控制台中被标记为测试请求。

永远不要在真实访客流量中发送 test: true——这仅用于你自己的探索性/接入测试。如果不加这个参数反复测试(例如反复用 curl、同一个 IP 多次调用),会像其他任何流量一样,真实地在你自己的 IP 上累积自学习信誉记录。

想直接在自己的网站上用 crytify_gate() 测试?把它放进选项数组里就行,不用自己去改请求体:

crytify_gate('cry_live_xxxxxxxxxxxx', ['test' => true]);

Usage

GET · 免费——不消耗额度

查询已认证 key 所属账户的每日剩余额度和套餐限制。适合在你自己的控制台中展示用量,或在额度耗尽前提前预警。

curl "https://api.crytify.com/v1/usage" \
  -H "Authorization: Bearer cry_live_xxxxxxxxxxxx"
{
  "user_id": 7,
  "plan": "free",
  "credits": {
    "daily_limit": 1000,
    "daily_used": 42,
    "daily_remaining": 958,
    "unlimited": false,
    "balance": 0,
    "reset_at": "2026-07-04T00:00:00Z"
  }
}

Me

GET · 免费——不消耗额度

返回当前使用的 API key 的元数据以及账户当前的套餐信息。适合在不打开控制台的情况下确认哪个 key/模式正在生效。

curl "https://api.crytify.com/v1/me" \
  -H "Authorization: Bearer cry_live_xxxxxxxxxxxx"
{
  "api_key": {
    "id": 22,
    "name": "Default Key",
    "prefix": "cry_live_b6ba5ef81c422782",
    "default_mode": "medium",
    "can_override_mode": false,
    "status": "active",
    "created_at": "2026-07-03 01:05:42"
  },
  "account": {
    "id": 7,
    "plan": "free"
  }
}

模式与额度

模式 额度 适用场景
easy2低摩擦的内容页面。
medium4表单、账户页面及通用保护的默认模式。
hard8登录、注册、结账、后台管理与 API 保护。

推荐传递的请求头

传递有用的浏览器请求头,但不要发送原始 cookie、authorization token、密码或密钥。

user-agent
accept
accept-language
accept-encoding
sec-fetch-site
sec-fetch-mode
sec-fetch-dest
sec-ch-ua
sec-ch-ua-mobile
sec-ch-ua-platform

错误代码

代码HTTP含义
invalid_json 400 请求体不是合法的 JSON。
missing_required_field 400 缺少必需字段,例如 ip。
invalid_ip 400 提交的 IP 地址无效。
invalid_api_key 401 API key 缺失或无效。
insufficient_credits 402 钱包额度不足。
rate_limited 429 请求过于频繁。
internal_error 500 内部错误。已扣除的额度会被退还。

执行示例

你的应用决定如何处理返回的决策。一个典型的预渲染拦截大致如下:

if ($decision === 'BLOCK') {
    http_response_code(403);
    exit('Blocked');
}

if ($decision === 'CHALLENGE') {
    header('Location: ' . $result['challenge']['url']);
    exit;
}

if (!empty($_GET['crytify_challenge_token'])) {
    // Send this token in the next /v1/trust call as challenge_token.
}

renderProtectedPage();

页面保护

SDK · 双层拦截

Crytify SDK 让你可以在页面内容被渲染或可见之前就把它从机器人面前隐藏起来。这里有两个互补的层级——搭配使用可获得最大覆盖面。

1

服务端拦截(PHP)

在渲染任何内容之前,在你的 PHP 代码中评估访客 IP 与请求头。可拦截所有机器人——包括不执行 JavaScript 的那些(curl、Python requests、Scrapy、wget)。

2

客户端拦截(JS)

<head> 中的脚本会立即隐藏页面,收集一致性元数据,只有在信任检查通过后才显示内容。

BrowserYour serverCrytify /v1/trust
               ↓ PHP 拦截(渲染前)

Browsercrytify-protect.jsYour endpointCrytify /v1/trust
                                  ↓ JS 拦截(可见前)

只有你的入口页面需要完整检查。 如果访客在已经运行过 crytify_gate() 的页面之后,稳定地到达其他受保护页面(结账、账户),可以改用 crytify_require_pass()——一种免费、仅基于 cookie 的检查,没有 API 调用也不消耗额度。 查看工作原理 →

JavaScript SDK

crytify-protect.js 是一个即插即用的脚本,加载后立即隐藏你的页面,收集浏览器指纹,并发送给你的后端。只有在后端确认访客被允许后,内容才会显示。

1. 嵌入到 <head> 中——放在其他任何脚本之前

<head>
  <!-- Must be the first script in <head> -->
  <script src="/crytify-protect.js"
          data-endpoint="/api/crytify-check"
          data-block-url="/blocked"
          data-timeout="5000">
  </script>
</head>

选项

属性 是否必需 说明
data-endpoint 你后端信任检查接口的 URL。JS 会把指纹 POST 到这里。
data-block-url 访客被拦截时重定向到这里。默认显示内联的拦截提示。
data-timeout 如果你的接口没有响应,多少毫秒后自动 fail open(照常显示内容)。默认:5000。
data-debug 设为 "true" 可在浏览器控制台打印决策日志。

2. 创建后端接口(data-endpoint)

JS 会向你的接口 POST { "fingerprint": { ... } }。你的接口调用 Crytify,并返回 { "allow": true } 或 { "allow": false }。

<?php
// /api/crytify-check.php — the endpoint crytify-protect.js calls

require 'CrytifyClient.php';

header('Content-Type: application/json');

$body        = json_decode(file_get_contents('php://input'), true);
$fingerprint = $body['fingerprint'] ?? null;

$crytify = new CrytifyClient('cry_live_xxxxxxxxxxxx');
$result  = $crytify->trust(
    CrytifyClient::resolveIp(),
    getallheaders(),
    ['fingerprint' => $fingerprint]
);

echo json_encode(['allow' => $result->isAllow(), 'reason' => $result->reason()]);
Fail-open 安全机制: 如果你的接口无法访问,或响应时间超过 data-timeout 设置的毫秒数,脚本会自动显示页面内容。这可以防止 Crytify 服务中断影响到你真实用户的正常访问。

PHP SDK

CrytifyClient.php 是一个无依赖的独立 PHP 类,可以放在项目的任意位置。把它当作 middleware 使用,在发送任何一个字节的 HTML 之前就拦截页面渲染。

下载

# Copy the file into your project
cp crytify-sdk/CrytifyClient.php your-project/lib/CrytifyClient.php

基本用法——服务端拦截

把这段代码放在你想保护的 PHP 页面最顶部,在任何输出之前。

<?php
require 'CrytifyClient.php';

$crytify = new CrytifyClient('cry_live_xxxxxxxxxxxx', mode: 'medium');

$result = $crytify->trust(
    CrytifyClient::resolveIp(),   // resolves CF-Connecting-IP / X-Forwarded-For automatically
    getallheaders(),
    ['path' => $_SERVER['REQUEST_URI'], 'method' => $_SERVER['REQUEST_METHOD']]
);

if ($result->isBlock()) {
    http_response_code(403);
    include 'blocked.html';
    exit;
}

if ($result->isChallenge()) {
    header('Location: ' . $result->challengeUrl());
    exit;
}

// Visitor passed — render your page normally

CrytifyResult 方法

方法返回值说明
isAllow() bool 访客通过时为 true。
isChallenge() bool 建议进行额外验证时为 true。
isBlock() bool 访客应被拒绝时为 true。
challengeUrl() ?string 决策为 CHALLENGE 时的 Crytify 托管验证页 URL。
decision() string 原始决策字符串:ALLOW、CHALLENGE 或 BLOCK。
trustScore() int 0–100。数值越高代表越可信。
riskScore() int 0–100。数值越高代表越可疑。
reason() string 决策对应的可读原因字符串。
isFailOpen() bool 因网络错误触发自动 fail-open 时为 true。

CodeIgniter 4 过滤器

对于 CI4 项目,可以使用提供的过滤器类以声明式方式保护路由。

// app/Config/Filters.php
public array $aliases = [
    'crytify' => \App\Filters\CrytifyGateFilter::class,
];

// app/Config/Routes.php — protect individual routes
$routes->get('checkout', 'OrderController::checkout', ['filter' => 'crytify']);

// Or protect an entire group
$routes->group('members', ['filter' => 'crytify'], function ($routes) {
    $routes->get('dashboard', 'MemberController::dashboard');
    $routes->get('profile',   'MemberController::profile');
});

浏览器指纹

在 /v1/trust 中传入 fingerprint 对象,可以补充仅凭服务器请求头无法获得的客户端一致性上下文。具体信号的处理逻辑是私有的,公开响应只会展示宽泛的原因分类。

公开分类

信号含义置信度
fingerprint_risk 客户端一致性上下文对该决策有所贡献。 公开分类
automation_risk 与自动化相关的上下文对该决策有所贡献。 公开分类
identity_risk 会话或身份一致性上下文对该决策有所贡献。 公开分类

用 JS 辅助工具采集指纹

crytify-fingerprint.js 会采集所有信号并返回一个普通对象。如果你想自己采集指纹并发送给服务器,而不使用自动隐藏页面的行为,可以单独使用它。

<script src="/crytify-fingerprint.js"></script>
<script>
crytifyFingerprint().then(function (fp) {
    // fp is a plain JS object — send it to your server
    fetch('/api/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            email:       document.getElementById('email').value,
            password:    document.getElementById('password').value,
            fingerprint: fp,   // <-- include fingerprint in your form submission
        }),
    });
});
</script>

之后你的服务器只需把 fingerprint 直接放进 /v1/trust 的请求体中传递即可。不需要新的 Crytify 接口。