Skip to content

About

用于VeriRandom的抽取证明服务端

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

VeriRandom Witness

最小可用的 VeriRandom 重放存证服务。服务端接收客户端导出的 DrawProof,用与客户端相同的 C# 验证内核重放,检查 proof 自洽性,然后用 ECDSA P-256 签发回执,并为每个客户端维护一个只追加的链锚。

当前范围

已实现:

  • POST /v1/proofs/attest:普通 OfflineReproducible 证明的重放、校验、签名、链锚
  • GET /v1/keys:keyId 和 SPKI 公钥(用于填进客户端)
  • GET /healthz:数据库和密钥健康检查
  • SQLite 幂等存储:proofId 重复提交返回原回执
  • 链状态:genesis / continuous / duplicate / behind / gap / broken / conflict / unchained
  • xUnit 测试:内核重放、结果一致性、回执签名与绑定、链锚

暂不包含:

  • 正式公证 POST /v1/notarizations
  • RFC 3161 TSA(客户端自己申请,服务端不需要)
  • 透明度日志 / Merkle root 发布
  • 限流、配额、管理后台
  • Windows 证书库 / CNG 非导出密钥(当前是 PFX)

前置

  • 开发机:.NET 10 SDK
  • 部署:Windows Server + IIS + .NET 10 Hosting Bundle(Hosting Bundle 已包含 .NET Runtime、ASP.NET Core Runtime 和 ANCM,不需要再单独装运行时)
  • 环境变量 WITNESS_KEY_PASSWORD,至少 12 个字符

本地运行

$env:WITNESS_KEY_PASSWORD = "change-me-please-12345"
dotnet run --project src/VeriRandom.Witness

开发环境 appsettings.Development.json 打开了 AutoGenerateKey,首次启动会在 data/keys/witness.pfx 生成 P-256 密钥。生产默认 AutoGenerateKey=false,请显式提供 PFX。

获取公钥:

Invoke-RestMethod http://localhost:5080/v1/keys

把返回的 publicKey 原样填入客户端 WitnessClient.WitnessPublicKey 常量,把 WitnessServiceUrl 指向服务根地址(例如 https://witness.example.com/)。

构建与 CI

dotnet build VeriRandom.Witness.sln -c Release
dotnet test VeriRandom.Witness.sln -c Release

.github/workflows/build.yml 会:

  1. checkout 本仓库
  2. 按 VERIRANDOM_KERNEL_SHA 把主仓库 checkout 到 .deps/verirandom
  3. 只 sparse-checkout 三个 Verification 目录
  4. build / test / publish

如果主仓库是私有的,在 workflow 的 checkout 步骤加 token: ${{ secrets.VERIRANDOM_READ_TOKEN }}。NuGet.config 已清空本机 Visual Studio 的 fallback 目录,CI 和本地都只使用 nuget.org。

Visual Studio 版本要求:项目目标是 net10.0,只能用 Visual Studio 2026(18.0+) 打开和构建。Visual Studio 2022 17.14 最高只支持 net9.0,会报“找不到指定的 SDK / Microsoft.NET.Sdk.Web”。如果暂时不想升级 VS,可以用 dotnet CLI 或 VS Code;不要把项目降级到 net9.0,它已经结束支持。

推送到 GitHub

仓库已经在本地初始化并完成首个提交,但还没有 remote:

git remote add origin https://github.com/<你的账号>/VeriRandom-Witness.git
git push -u origin main

推送后 workflow 会自动跑。建议在仓库的 Settings → Secrets and variables → Actions → Variables 里设置 VERIRANDOM_KERNEL_SHA,以后升级内核只改变量,不改 workflow;未设置时使用 workflow 里的固定 SHA 兜底。

验证内核同步

服务端不引用整个 SecRandom.Core(会带入 Avalonia 等 UI 依赖),只链接验证相关源文件。

  • 固定提交记录在 kernel.lock.json
  • 本地开发:.\scripts\fetch-kernel.ps1,或直接用同级的 ..\SecRandom
  • CI:签出 WinFunan/VeriRandom 到 .deps/verirandom,只拉三个 Verification 目录
  • 升级:修改 kernel.lock.json 和 CI 的 VERIRANDOM_KERNEL_SHA,跑完整测试

文件清单在 src/VeriRandom.Witness.Kernel/VeriRandom.Witness.Kernel.csproj,保持显式列表,不要改成 glob。

API

POST /v1/proofs/attest

请求头:

X-SecRandom-Client-Id: <guid>
Content-Type: application/json

请求体:客户端原样发送的 DrawProof JSON。

成功响应:

{
  "token": "<base64url-payload>.<base64url-der-signature>",
  "keyId": "p256-...",
  "chain": {
    "status": "continuous",
    "headIndex": 2,
    "headHash": "...",
    "breaks": 0
  }
}

失败响应:

{ "error": "proof_inconsistent", "detail": "..." }

GET /v1/keys

{
  "keyId": "p256-...",
  "algorithm": "ECDSA-P256-SHA256",
  "publicKey": "<SPKI base64>",
  "publicKeyFormat": "spki-base64",
  "tokenFormat": "base64url(json-payload).base64url(der-signature)",
  "attestationUrl": "/v1/proofs/attest"
}

GET /healthz

数据库可读且密钥已加载时返回 200;否则返回 503。

IIS 发布

dotnet publish src/VeriRandom.Witness/VeriRandom.Witness.csproj `
  -c Release -r win-x64 --self-contained false -o artifacts/publish

部署要点:

  1. 新建独立站点和独立应用池,不要挂在现有 Web 应用下。
  2. 应用池:No Managed Code、1 个 worker、关闭 Web Garden、关闭 Overlapped Recycle。
  3. 给应用池身份:
    • 发布目录:读/执行
    • data 目录:修改
    • PFX 文件:读
  4. web.config 已包含 hostingModel="inprocess" 和 maxAllowedContentLength=8MB。
  5. 通过 IIS 应用池环境变量或机器级环境变量设置 WITNESS_KEY_PASSWORD。不要把密码写进 appsettings.json。
  6. 必须只开 HTTPS。如果前面有 Cloudflare,用 Full (strict),并限制源站只接受 Cloudflare IP 或走 Cloudflare Tunnel。
  7. 备份 data/keys/witness.pfx 和 data/witness.db。PFX 丢了就没法继续用同一把钥匙签名。

与客户端的契约

服务端签名的 canonical hash 是 AttestedProofHash.Compute,它逐字段复制了客户端 WitnessClient.ComputeAttestedProofHash:

  • 字段顺序不能变
  • null 写成 -1
  • 字符串长度、int32、int64 都用小端
  • 时间用 CreatedAtUtc.UtcDateTime.Ticks
  • chain、beacon、witness.receipt、witness.timestampToken 不参与该 hash

改动这里必须同时改客户端并跑跨端测试。

安全边界

  • 当前服务是单机 SQLite;不要开 Web Garden,也不要在多台机器上同时写同一个数据库。
  • 服务是“你自己运营的见证”,不是独立第三方。它能证明“服务端在某时刻签收了这份 proof”,不能替代独立运营者或本地重放。
  • 生产环境建议把 PFX 换成 Windows 证书库/CNG 非导出密钥,并制定轮换与备份方案。
  • 公网部署前至少加限流(ASP.NET Core RateLimiter 或 Cloudflare WAF),避免签名接口被滥用。

测试

dotnet test VeriRandom.Witness.sln -c Release

License

GPL-3.0-only,因为链接了 VeriRandom / SecRandom 的验证源码。见 LICENSE 和 THIRD_PARTY_NOTICES.md。

About

用于VeriRandom的抽取证明服务端

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages