术语表 /开发者参考
PaymentRequest
- PaymentRequest 是什么?
- PaymentRequest 是 BIP70 的外层信封:它将序列化的 PaymentDetails 数据块与证书链和签名封装在一起,使付款方可以核实是谁在发出请求。
规定于 BIP-70。
PaymentRequest 是一种消息,可让钱包显示公司名称,而不是一串字符。它有五个字段,其中最关键的两个是 pki_type(取值为 none、x509+sha256 或 x509+sha1 之一)和对序列化详情的签名 signature。对于今天的付款人,这一教训在协议之外依然成立:付款界面上的名称,其可信程度只取决于为它背书的人。
运作方式
状态:已废弃。从0.9.0起,Bitcoin Core 内置了对 PaymentRequest 的处理,直到0.20.0于2020年6月3日将其移除,目前没有仍在维护的钱包会解析该消息。
五个字段,按顺序如下:
payment_details_version,一个32位整数,默认值为1。它从未递增过。pki_type,一个字符串,默认值为 "none"。其他可选值为 "x509+sha256" 和 "x509+sha1"。pki_data,包含一个 X509Certificates 结构,商户的叶证书排在最前,其后是各中间证书。serialized_payment_details,必填项,即本词汇表其他条目所述的不透明字节串。signature,用于证明整条消息来自证书持有者的字节。
签名流程中有一个小技巧。商户填写所有字段,将 signature 设为空,序列化完整的消息,对其计算哈希,用叶证书对应的私钥对该哈希签名,然后把签名写入刚才留空的字段。验证方再次将该字段清空,重新序列化,然后进行校验。流程简单,自成一体,除证书之外不依赖任何其他东西。
问题恰恰出在这种依赖上。验证证书链要求钱包持有根证书库,桌面软件从操作系统继承该证书库,而移动软件常常处理不当。即使实现正确,也只能证明某家证书颁发机构为某个域名作过证明,而根证书库中有数百家机构,其中任何一家都可以为任何名称签发证书。所提供的选项中最弱的 x509+sha1 老化得尤其严重:BIP70 撰写四年之后,2017年2月23日公布了一次可实际生成的 SHA-1碰撞。
在哪里会遇到它
仍在使用 PaymentRequest 这个名称的地方有两处,其中只有一处与比特币有关。
第一处是存档的代码和文档,其中 BIP71 的 MIME 类型 application/bitcoin-paymentrequest 用于标记商户服务器返回的响应。第二处是现代网络平台,PaymentRequest 在那里指一种用于银行卡和已存储支付方式结账的浏览器 API,与本协议毫无关系。如今用到这个词的开发者几乎肯定指的是浏览器那一种,而混淆两者是检索旧版比特币文档时最常见的错误。
对购买比特币的人来说,要点在于身份如何与付款关联。交易所通过账户和 KYC 解决这一问题,平台知道您是谁,您则依赖平台的声誉。自托管的做法是由您自己核对地址。BIP70 尝试了第三条路,借用网络的证书体系,而这条路已经走不通了。
PaymentRequest vs PaymentDetails
PaymentRequest 是信封,PaymentDetails 是信封里的信。查看信封可以知道谁签了名、用了哪张证书,却无从得知请求的具体内容。金额、脚本、有效期和备注都在内层消息中,内层消息以未解析的字节串形式放在信封里,正是为了避免因重新编码而使签名失效。钱包必须先验证前者,才能信任后者中的任何内容。