跳到主要内容

密钥配置

密钥对请在你自己的电脑上生成。平台不会接收、也不会存储你的私钥;你只需在商户后台登记公钥,后台会引导你完成一次性的 proof 签名,用来证明你持有对应的私钥。

请使用 OpenSSL 3.0 或更高版本。旧版 OpenSSL 以及 macOS 自带的 LibreSSL 可能不支持下面的命令。Windows 请使用 PowerShell 5.1+;macOS / Linux 请使用 Bash 或 Zsh。所有步骤在同一个终端、保存 priv.pem 和 pub.pem 的目录里执行。

1. 安装 OpenSSL​

winget install --id ShiningLight.OpenSSL.Light --exact --source winget --accept-source-agreements --accept-package-agreements
$opensslDirs = Get-ChildItem "$env:ProgramFiles\OpenSSL*\bin", "${env:ProgramFiles(x86)}\OpenSSL*\bin" -Directory -ErrorAction SilentlyContinue
$env:Path = ($opensslDirs.FullName -join ";") + ";" + [Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [Environment]::GetEnvironmentVariable("Path", "User") + ";" + $env:Path
openssl version

如弹出系统授权,请确认。若提示找不到 winget,请先从 Microsoft Store 安装或更新“应用安装程序”,或从 Shining Light Productions 手动安装 OpenSSL Light。

确认输出为 OpenSSL 3.x 或更高版本再继续;若仍显示 1.x 或 LibreSSL,请先检查安装和 PATH。

2. 生成密钥对​

各系统命令相同。

openssl genpkey -algorithm ed25519 -out priv.pem
openssl pkey -in priv.pem -pubout -out pub.pem

把 pub.pem 粘贴到商户后台登记凭证,priv.pem 自行妥善保管。

3. 转换成 SDK 需要的私钥格式​

SDK 不读 PEM。剥掉 ASN.1 头,把 32 字节 seed 和 32 字节公钥拼成 64 字节格式,再转 base64。私钥 PKCS8 DER 是 48 字节(前 16 字节固定头 + 32 字节 seed);公钥 SPKI DER 是 44 字节(前 12 字节固定头 + 32 字节公钥)。

& {
# 剥掉 ASN.1 头,拿裸字节
openssl pkey -in priv.pem -outform DER -out private.der
if ($LASTEXITCODE -ne 0) { throw "OpenSSL: private key export failed" }
openssl pkey -pubin -in pub.pem -outform DER -out public.der
if ($LASTEXITCODE -ne 0) { throw "OpenSSL: public key export failed" }
$privateDer = [IO.File]::ReadAllBytes((Join-Path $PWD.Path "private.der"))
$publicDer = [IO.File]::ReadAllBytes((Join-Path $PWD.Path "public.der"))
if ($privateDer.Length -ne 48 -or $publicDer.Length -ne 44) { throw "Expected Ed25519 keys" }

# 拼成 64 字节格式(seed + 公钥),转 base64
[Convert]::ToBase64String([byte[]]($privateDer[16..47] + $publicDer[12..43]))
Remove-Item -LiteralPath private.der, public.der
}

输出就是商户私钥配置项的值(Go 里是 MerchantPrivateKeyBase64,其他语言见 SDK 配置)。它是机密,请像其他凭据一样保管,不要粘贴到商户后台。登记时后台要的 proof 签名是另一个值,两者不是一回事。