时间戳 API — 快速开始
一次 HTTP 调用。没有密钥、账号或注册表单。你的文件留在原处,只有它的 SHA-256 上路。
# 当前的通用时间 curl https://beattime.live/api/now/ # 为文件打时间戳:本地计算哈希,只发送哈希 sha256sum contract.pdf curl -X POST https://beattime.live/api/proof/stamp \ -H 'Content-Type: application/json' \ -d '{"digest":"<64 hex characters>"}'
集成就这些。没有要注册的东西,没有需要轮换的令牌,也没有要谈判的配额——这项服务免费,并将一直免费。
返回的内容
打戳返回的是此刻的记录状态。稍后,同一个哈希会返回更多内容:先是签名,然后是外部锚定。
- digest
- 你发送的 SHA-256(小写)。这是我们对你的文件所能看到的全部。
- beat
- 以 .beat 时间表示的时刻——一个通用读数,不带时区。
- utc
- 同一时刻的 UTC 表示,精确到微秒。
- seq
- 在只可追加日志中的位置。编号不会重复,也不会移动。
- week
- 该时间戳所属默克尔树对应的 ISO 周。
- chain_hash
- 把这条记录与上一条相连,因此删除任何一条都会让链条明显断裂。
- week_root
- 每周默克尔根。在本周封存之前,它是暂定值,仍会变动。
- inclusion_proof
- 兄弟哈希及其所在一侧(L 或 R)。有了它们,你可以自行重算根值——这正是证明不依赖我们的原因。
- root_signature
- 对已冻结的周根所做的 Ed25519 签名。周封存后出现。
- ots_status
- 比特币锚定状态:等待确认时为 pending,确认后为 bitcoin 并附区块高度。
- anchors
- 周根所对应的银行参考号——一个不依赖任何区块链的锚点。
“本周尚未封存”是正常回复,而不是错误。
新打的时间戳还没有签名和锚点,因为它所属的那一周尚未封存。封存发生在 ISO 周结束时,比特币证明大约一天后跟上。稍后用同一个哈希再查一次,缺少的字段就会出现。在此期间,已记录的时间不会改变。
对同一文件打两次时间戳
第一次打的时间戳永远算数。再次发送同一个哈希,你会拿回原始记录——同样的时间、同样的序号——状态码是 200 而不是 201。因此重试是安全的:丢失的响应或过于急躁的客户端都无法把你的时间戳往后推。
201 Created → 首次打戳 200 OK → 已打过戳,返回原始时间戳 400 → 哈希不是 64 位十六进制字符 429 → 超出速率限制,请稍候重试
限额与 CORS
限额按 IP 地址计算,目的是不让某一个客户端挤占其他人。对于正常集成所做的一切,这些额度是刻意留足的。
| 接口 | 限额 |
|---|---|
| POST /api/proof/stamp | 20 / min |
| GET /api/proof/verify | 120 / min |
| GET /api/proof/cert/<digest> | 10 / min |
| 其余接口(时间、换算、同步) | 300 / min |
每个接口都带 Access-Control-Allow-Origin: * 响应,因此可以直接从浏览器调用。经由 Tor 的请求限额更高,因为一个出口节点背后是许多人。
现成的客户端
单文件、零依赖、Apache-2.0:Python、PHP、JavaScript、C# 与 C++17。把其中一个复制到你的项目,或查阅完整参考。
它不是什么
在以此为基础开发之前值得知道,我们宁可在这里说清楚,也不愿你在评审时才发现:
- 不是 eIDAS 意义上的合格信任服务,因此时间戳不享有第 41 条的法律推定。它是证据,不是裁决。
- 证明的是存在与完整性,而不是作者身份。时间戳只说明这段字节在那时已经存在且此后未被改动,并不说明是谁做的,也不说明内容是否属实。
- 不是 RFC 3161。我们目前不支持该协议,因此期待它的工具——
openssl ts、signtool——无法与这个 API 通信。 - 记录是公开且永久的。哈希无法撤回,不要为你不希望被列出的内容打戳。