跳到主要内容

身份验证概述

VertexPlay API 使用多层身份验证机制来确保 API 请求的安全性。

验证流程

请求标头

所有 API 请求都必须包含以下标头:

验证请求 (/v2/auth)

标头类型必填说明
Content-Typestring必须为 application/json
x-agentidstring平台端代理 ID
x-timestampstringUnix 时间戳(毫秒)
x-noncestring32 字元隨机字符串(用于防重放攻击)
x-signaturestringSHA256 签章

其他 API 请求

标头类型必填说明
AuthorizationstringBearer token,格式:Bearer {accessToken}
Content-Typestring必须为 application/json
x-agentidstring平台端代理 ID
x-timestampstringUnix 时间戳(毫秒)
x-noncestring32 字元隨机字符串
x-signaturestringSHA256 签章

签章生成

签章使用 SHA256 算法生成,确保请求的完整性和真实性。

签章步骤

  1. 准备签章字符串:将以下参数按順序连接

    agentId + timestamp + nonce + requestBody
  2. 生成签章:使用 SHA256 算法

    signature = SHA256(signatureString)
  3. 添加到请求标头:将生成的签章放入 x-signature 标头

Node.js 范例

const crypto = require('crypto');

function generateSignature(agentId, timestamp, nonce, requestBody) {
// 将请求体转为字符串
const bodyString = JSON.stringify(requestBody);

// 组合签章字符串
const signatureString = agentId + timestamp + nonce + bodyString;

// 生成 SHA256 签章
const signature = crypto
.createHash('sha256')
.update(signatureString)
.digest('hex');

return signature;
}

// 使用范例
const agentId = 'integratorNBTest04';
const timestamp = Date.now().toString();
const nonce = crypto.randomBytes(16).toString('hex');
const requestBody = {
cipherText: 'G0ZMDELeJwx+7JcIfIFO...'
};

const signature = generateSignature(agentId, timestamp, nonce, requestBody);

Python 范例

import hashlib
import json
import time
import secrets

def generate_signature(agent_id, timestamp, nonce, request_body):
# 将请求体转为字符串
body_string = json.dumps(request_body, separators=(',', ':'))

# 组合签章字符串
signature_string = agent_id + timestamp + nonce + body_string

# 生成 SHA256 签章
signature = hashlib.sha256(
signature_string.encode('utf-8')
).hexdigest()

return signature

# 使用范例
agent_id = 'integratorNBTest04'
timestamp = str(int(time.time() * 1000))
nonce = secrets.token_hex(16)
request_body = {
'cipherText': 'G0ZMDELeJwx+7JcIfIFO...'
}

signature = generate_signature(agent_id, timestamp, nonce, request_body)

数据加密

所有请求的敏感数据都使用 AES-256-GCM 加密,响应为明文 JSON 格式。

加密格式

{
"cipherText": "ivBase64(16字元) + authTagBase64(24字元) + encryptedDataBase64"
}

加密参数

  • 算法:AES-256-GCM
  • 密鑰長度:256 位(32 字節)
  • IV 長度:96 位(12 字節)
  • 认证标签長度:128 位(16 字節)

cipherText 结构说明

cipherText 由三个部分组成,全部使用 base64 編码:

  1. IV (Initialization Vector)

    • 長度:12 bytes
    • Base64 編码后:16 字元
    • 位置:cipherText[0:16]
  2. Auth Tag (认证标签)

    • 長度:16 bytes
    • Base64 編码后:24 字元
    • 位置:cipherText[16:40]
  3. Encrypted Data (加密数据)

    • 長度:变長,取决于原始数据
    • Base64 編码
    • 位置:cipherText[40:]

解密范例 (Node.js)

const crypto = require('crypto');

const AES_ALGORITHM = 'aes-256-gcm';

/**
* 解密 cipherText
* @param {string} key - AES 密鑰 (hex 格式)
* @param {string} cipherText - 加密文本
* @returns {Object} - 解密后的 JSON 物件
*/
function symmetricDecrypt(key, cipherText) {
try {
const aesKey = Buffer.from(key, 'hex');

// 从密文分离 iv, authTag 和加密资料
const ivLength = 16; // base64 編码的 12 bytes
const authTagLength = 24; // base64 編码的 16 bytes

const ivBase64 = cipherText.substring(0, ivLength);
const authTagBase64 = cipherText.substring(ivLength, ivLength + authTagLength);
const encryptedData = cipherText.substring(ivLength + authTagLength);

const aesIv = Buffer.from(ivBase64, 'base64');
const authTag = Buffer.from(authTagBase64, 'base64');

// 建立解密器
const decipher = crypto.createDecipheriv(AES_ALGORITHM, aesKey, aesIv);
decipher.setAuthTag(authTag); // 设置认证标签,GCM 会自动验证完整性

// 解密
let decrypted = decipher.update(encryptedData, 'base64', 'utf8');
decrypted += decipher.final('utf8'); // 如果 authTag 验证失敗,这裡会拋出错误

return JSON.parse(decrypted);
} catch (e) {
throw new Error(`Symmetric Decryption Failed: ${e.message}`);
}
}

// 使用范例
const key = 'your-32-byte-hex-key'; // 64 个 hex 字元 = 32 bytes
const cipherText = 'G0ZMDELeJwx+7JcI...'; // 完整的 cipherText

try {
const decryptedData = symmetricDecrypt(key, cipherText);
console.log('Decrypted data:', decryptedData);
} catch (error) {
console.error('Decryption error:', error.message);
}

加密范例 (Node.js)

/**
* 加密数据
* @param {string} key - AES 密鑰 (hex 格式)
* @param {Object} data - 要加密的 JSON 物件
* @returns {string} - 加密后的 cipherText
*/
function symmetricEncrypt(key, data) {
try {
const aesKey = Buffer.from(key, 'hex');

// 生成隨机 IV (12 bytes)
const aesIv = crypto.randomBytes(12);

// 建立加密器
const cipher = crypto.createCipheriv(AES_ALGORITHM, aesKey, aesIv);

// 加密数据
const jsonString = JSON.stringify(data);
let encrypted = cipher.update(jsonString, 'utf8', 'base64');
encrypted += cipher.final('base64');

// 获取认证标签 (16 bytes)
const authTag = cipher.getAuthTag();

// 组合 cipherText: ivBase64 + authTagBase64 + encryptedData
const cipherText = aesIv.toString('base64') +
authTag.toString('base64') +
encrypted;

return cipherText;
} catch (e) {
throw new Error(`Symmetric Encryption Failed: ${e.message}`);
}
}

// 使用范例
const data = {
username: 'player001',
amount: 100
};

const cipherText = symmetricEncrypt(key, data);
console.log('Encrypted cipherText:', cipherText);

错误处理

验证错误码

状态码说明
84解密失敗 - 可能是密鑰错误或数据损壞
83认证失敗 - 签章验证失敗或参数错误

错误响应格式

{
"code": 83,
"message": "Signature verification failed",
"logUUID": "6589bf8d-fe74-48bd-841a-71bf8f848f86"
}

安全建议

  1. 保护 Secret Key:絕不在平台端代码或公开位置存儲 Secret Key
  2. 使用 HTTPS:所有 API 请求必须通过 HTTPS 传输
  3. 时间戳验证:确保时间戳在合理范围內(建议 ±1 分钟)
  4. Nonce 唯一性:每个请求使用唯一的 nonce 防止重放攻击
  5. Token 管理:定期刷新 accessToken,不要長期使用同一个 token
  6. 错误处理:妥善处理认证错误,避免洩露敏感信息

下一步

了解如何获取 Access Token 来开始使用 API。