Skip to content

签名规则

算法与密钥

  • 摘要:SHA-256
  • 签名:ECDSA ES256(曲线 P-256 + SHA-256,签名值为 DER,再 Base64)
  • 密钥生成:
bash
openssl ecparam -name prime256v1 -genkey -noout -out priKey.pem
openssl ec -in priKey.pem -pubout -out pubKey.pem
# 建议再转为 PKCS#8:
openssl pkcs8 -topk8 -nocrypt -in priKey.pem -out priKey_pkcs8.pem

私钥自行保管用于加签;公钥提交给平台用于验签。

Digest

text
Digest = "SHA-256=" + Base64(SHA256(raw_body_bytes))
  • POST / PUT / PATCH:对最终发出的原始 HTTP body 字节计算(不要重新序列化 JSON)
  • GET / DELETE:对空字节串计算

Canonical Signing String

仅覆盖以下 4 行,顺序固定;字段名小写;冒号后单个空格\n(LF)换行:

text
(request-target): <method小写> <path>[?<query>]
x-timestamp: <X-Timestamp>
x-nonce: <X-Nonce>
digest: <Digest>

示例:

text
(request-target): post /coin/v1/exchange/quote
x-timestamp: 1710000000
x-nonce: a9f3c1d47e8b9a2c
digest: SHA-256=Base64DigestValue

Authorization

text
hashBytes    = SHA256(UTF8(canonicalString))
signature    = ECDSA_SIGN_DER(privateKey, hashBytes)
signatureB64 = Base64(signature)

Authorization =
  Signature keyId="<X-Merchant-Id>",alg="ES256",headers="(request-target) x-timestamp x-nonce digest",signature="<signatureB64>"

服务端验签与防重放

  1. 校验 Digest 与原始 body 一致
  2. 重建 Canonical String 并验签 Authorization.signature
  3. X-Timestamp 窗口:±300s
  4. X-Nonce 防重放:5 分钟内同一 X-Merchant-Id + X-Nonce 不可重复