【比特币】 BIP - 0070 详解

标签: 比特币BIPBIP70
664人阅读 评论(0) 收藏 举报
分类:

BIP - 0070 详解


  BIP: 70
  Layer: Applications
  Title: 支付协议
  Author: Gavin Andresen <gavinandresen@gmail.com>
          Mike Hearn <mhearn@bitcoinfoundation.org>
  Comments-Summary: No comments yet.
  Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0070
  Status: Final
  Type: Standards Track
  Created: 2013-07-29

摘要

这个BIP描述了一个商家和他们的客户之间的通信协议,使客户更好的体验和更好的安全性,以抵抗付款过程中的中间人攻击。

动机

当前,最小比特币支付协议的操作如下:

  1. 客户将物品添加到网上购物篮,并决定使用比特币支付。
  2. 商家生成一个唯一的付款地址,将其与客户的订单相关联,并要求客户支付。
  3. 客户从商家的网页上复制比特币地址,并将其粘贴到他们正在使用的任何钱包中,或者遵循比特币链接,并且他们的钱包将以支付的金额启动。
  4. 客户授权支付商户的地址,并通过比特币P2P网络广播交易。
  5. 商户的服务器检测到付款,并在充分的交易确认后认为交易最终。

这个BIP扩展了上述协议,以支持几个新的功能:

  1. 人类可读,安全的支付目的地 - 客户将被要求授权支付给“example.com”,而不是一个难以辨认的,34个字符的比特币地址。
  2. 安全的付款证明,客户可以在与商家发生纠纷的情况下使用。
  3. 在交易获得硬件钱包授权之前,用中间人攻击来抵御商人的比特币地址和攻击者的地址。
  4. 付款收到的消息,所以客户立即知道商家已经收到,并已经处理(或正在处理)他们的付款。
  5. 退款地址由客户的钱包软件自动提供给商户,因此商家在退款超额付款或因某种原因无法完成的订单前不必联系客户。

协议

这个BIP描述使用Google Protocol Buffers编码的支付协议消息,使用X.509证书进行验证,并通过http / https进行通信。 未来的BIP可能会将此支付协议扩展到其他编码,PKI系统或传输协议。

支付协议由三个消息组成; PaymentRequest,Payment和PaymentACK,并以某种方式从客户开始指示他们准备付款,商家的服务器用PaymentRequest消息响应:

这里写图片描述

消息

Protocol Buffers消息在 paymentrequest.proto https://github.com/bitcoin/bips/blob/d2a8fb089d7010d839530f879e07edc4e48b84fa/bip-0070/paymentrequest.proto 中定义。

Output

PaymentRequest消息中使用输出来指定应该发送付款(或付款的一部分)的位置。 它们也用于支付消息来指定退款的发送地点。

    message Output {
    optional uint64 amount = 1 [default = 0];
        optional bytes script = 2;
    }
字段 说明
amount satoshis的数量(0.00000001 BTC)将被支付
script 应该发送付款的“TxOut”脚本。 这通常是标准的比特币交易脚本之一(例如pubkey OP_CHECKSIG)。 这是可选的,以便将来对这个协议进行扩展,从主公钥和PaymentRequest数据本身派生输出。

PaymentDetails/PaymentRequest

支付请求被分成两个消息以支持未来的可扩展性。 大部分信息都包含在PaymentDetails消息中。 它被包裹在PaymentRequest消息中,其中包含关于商家和数字签名的元信息。

    message PaymentDetails {
        optional string network = 1 [default = "main"];
        repeated Output outputs = 2;
        required uint64 time = 3;
        optional uint64 expires = 4;
        optional string memo = 5;
        optional string payment_url = 6;
        optional bytes merchant_data = 7;
    }
字段 说明
network 在生产比特币网络上支付“主要”,或者在测试网络上支付“测试”。 如果一个客户端收到一个不支持网络的PaymentRequest,它必须拒绝这个请求。
outputs 比特币将被发送的一个或多个输出。 如果outputs.amount的总和为零,则会询问客户需要付多少钱,比特币客户端可以选择任何或全部输出(如果有多个)以进行支付。 如果产出金额之和不为零,则要求客户支付金额,并将金额分配到非零金额的产出(如果有多于一个的产出;零金额的产出应 被忽略)。
time 在创建PaymentRequest时,使用Unix时间戳(自UTC-Jan-1970 UTC以来的秒数)。
expires Unix时间戳(UTC)之后,PaymentRequest应该被认为是无效的。
memo UTF-8编码的纯文本(无格式)注释应该显示给客户,解释这个PaymentRequest的用途。
payment_url 安全(通常是https)可能会发送付款消息(见下文)以获取PaymentACK的位置。
merchant_data 商家可能使用的任意数据来标识PaymentRequest。 如果商家不需要将付款与PaymentRequest相关联,或者如果他们将每个PaymentRequest与单独的付款地址相关联,则可以省略。

PaymentDetails中指定的payment_url应至少保持有效,直到PaymentDetails过期(或者如果PaymentDetails没有过期,则尽可能长)。 请注意,这与基础支付请求中的任何状态更改无关; 例如取消订单不应该使payment_url无效,因为重要的是商家的服务器可以记录错误付款以便退还付款。

PaymentRequest是PaymentDetails(可选)绑定到商人的身份:

    message PaymentRequest {
        optional uint32 payment_details_version = 1 [default = 1];
        optional string pki_type = 2 [default = "none"];
        optional bytes pki_data = 3;
        required bytes serialized_payment_details = 4;
        optional bytes signature = 5;
    }
字段 说明
payment_details_version 请参阅下面的版本/升级的讨论。
pki_type 公钥基础设施(PKI)系统被用来识别商家。 所有的实现应该支持“none”,“x509 + sha256”和“x509 + sha1”。
pki_data PKI系统数据,标识商家,可用于创建数字签名。 对于X.509证书,pki_data包含一个或多个X.509证书(请参见下面的证书部分)。
serialized_payment_details 协议缓冲区序列化的PaymentDetails消息。
签名 数字签名在PaymentRequest消息的协议缓冲器序列化变体的散列上,所有序列化字段以数字顺序序列化(所有当前协议缓冲器实现以数字顺序序列化字段)并且使用与pki_data中的公钥对应的私钥进行签名。 未设置的可选字段不会被序列化(但是,将字段设置为其默认值将导致其被序列化并且会影响签名)。 序列化之前,必须将签名字段设置为空值,以便该字段包含在签名的PaymentRequest哈希中,但不包含数据。

当比特币钱包应用程序收到PaymentRequest时,它必须通过执行以下操作来授权付款:

  1. 如果pki_type不是“none”,则使用PKI系统验证商家的身份和签名。
  2. 验证客户的系统unix时间(UTC)在PaymentDetails.expires之前。 如果不是,则支付请求必须被拒绝。
  3. 显示商户的身份,询问客户是否要提交付款(例如在第一个X.509证书中显示“通用名称”)。

大于50,000字节的PaymentRequest消息应该被钱包应用拒绝,以减轻拒绝服务攻击。

Payment

付款消息在客户授权付款后发送:

    message Payment {
        optional bytes merchant_data = 1;
        repeated bytes transactions = 2;
        repeated Output refund_to = 3;
        optional string memo = 4;
    }
字段 说明
merchant_data 从PaymentDetails.merchant_data复制。 商家可以使用发票号码或任何其他数据来将付款与PaymentRequests进行匹配。 请注意,恶意客户可能会修改merchant_data,因此应以某种方式进行身份验证(例如,使用仅商户密钥进行签名)。
transactions 一个或多个有效的已签名比特币交易完全支付PaymentRequest
refund_to 如有必要,商户可以返回一个或多个输出资金。 商户可以在支付请求时间之后使用这些输出返还资金长达2个月。 在这段时间到期之后,各方必须商议是否需要返还资金。
memo UTF-8编码,从客户到商家的纯文本注释。

如果客户授权付款,那么比特币客户端:

  1. 创建并签署一个或多个符合(支付全额)PaymentDetails.outputs的交易
  2. 验证客户的系统unix时间(UTC)仍然在PaymentDetails.expires之前。 如果不是,应该取消付款。
  3. 在比特币P2P网络上广播交易
  4. 如果指定了PaymentDetails.payment_url,则将支付消息发送到该URL。 付款消息被序列化并作为POST请求的主体发送。

与payment_url服务器通信的错误应该传达给用户。 在商户的服务器接收到多个相同的支付消息的个人PaymentRequest的情况下,它必须承认每个。 从商家的服务器发送的第二个和另外的PaymentACK消息可以根据备注字段而变化以指示支付的当前状态(例如在网络上看到的确认的数量)。 这是必需的,以确保在传输过程中传输级别失败的情况下,比特币客户端可以通过重新发送付款消息来进行恢复。

PaymentDetails.payment_url应该是安全的,以防止可能改变Payment.refund_to的中间人攻击(如果使用HTTP,它必须是TLS保护的)。

通过HTTP发送付款消息的电子钱包软件必须设置适当的Content-Type和Accept头,如BIP 71中所述:

Content-Type: application/bitcoin-payment
Accept: application/bitcoin-paymentack

当商家的服务器收到付款消息时,必须确定交易是否满足付款条件。 当且仅当他们这样做,它应该在比特币p2p网络上广播交易。

大于50,000字节的支付消息应该被商家的服务器拒绝,以减轻拒绝服务攻击。

PaymentACK

PaymentACK是支付协议中的最终消息。 它是从商家的服务器发送到比特币钱包以响应支付消息:

    message PaymentACK {
        required Payment payment = 1;
        optional string memo = 2;
    }
字段 说明
payment 触发此PaymentACK的付款消息的副本。 如果客户实现另一种将Payments与PaymentACK关联的方式,则客户可以忽略它。
memo 应向客户显示UTF-8编码的注释,提供交易状态(例如“为接受处理的十一种纸币支付1 BTC”)。

大于60,000字节的PaymentACK消息应该被钱包应用拒绝,以减轻拒绝服务攻击。 这大于支付和PaymentRequest消息的限制,因为PaymentACK包含完整的支付消息。

本地化

支持多种语言的商家应该生成特定于语言的PaymentRequests,并将该语言与请求相关联,或者在请求的merchant_data中嵌入语言标签。 他们还应根据原始请求生成特定于语言的PaymentACK。

例如:希腊语客户浏览希腊语版本的商人网站时,会点击一个“Αγοράτώρα”链接,该链接会生成一个Paymentntquest,其中merchant_data设置为“lang = el&basketId = 11252”。 客户支付,他们的比特币客户端发送支付信息,而商家的网站用PaymentACK.message回答“σαςευχαριστούμε”。

证书

默认的PKI系统是X.509证书(与用于验证Web服务器的系统相同)。 当pki_type是“x509 + sha256”或“x509 + sha1”时,pki_data的格式是协议缓冲器编码的证书链:

    message X509Certificates {
        repeated bytes certificate = 1;
    }

如果pki_type是“x509 + sha256”,则使用SHA256算法对PaymentRequest消息进行散列,以产生经过签名的消息摘要。 如果pki_type是“x509 + sha1”,则使用SHA1算法。

每个证书都是DER [ITU.X690.1994] PKIX证书值。 包含数字签名PaymentRequest的实体的公钥的证书必须是第一个证书。 这必须附加额外的证书,每个后续证书是用于证明前一个证书的证书,直到(但不包括)受信任的根权威机构。 受信任的根权限可以包括在内。 收件人必须根据[RFC5280]验证证书链,如果发生验证失败,则拒绝PaymentRequest。

受信任的根证书可以从操作系统获得; 如果在没有操作系统的设备上进行验证,则推荐使用Mozilla根存储。

可扩展性

协议缓冲区序列化格式被设计为可扩展的。 特别是,可以将新的可选字段添加到消息中,并且将被旧的实现忽略(但是保存/重新传输)。

PaymentDetails消息可以用新的可选字段进行扩展,仍然被认为是“版本1”。 旧的实现将能够验证包含新字段的PaymentRequests的签名,但是(显然)将无法显示新的可选字段中包含的任何信息给用户。

如果商家在未来的某个时候有必要生成PaymentRequest消息,而这些消息只能被新的实现所接受,那么他们可以通过定义一个version = 2的新的PaymentDetails消息来实现。 旧的实现应该让用户知道他们需要升级他们的软件,当他们得到一个上传版本PaymentDetails消息。

在本规范中需要扩展消息的实现应使用从1000开始的标签,并通过pull-req更新扩展页面以避免与其他扩展冲突。

参考

BIP 0071:支付协议MIME类型

BIP 0072:支付协议比特币:URI扩展

公钥基础设施(X.509)工作组:http://datatracker.ietf.org/wg/pkix/charter/

协议缓冲区:https://developers.google.com/protocol-buffers/

参考实现

创建付款请求生成器:https://bitcoincore.org/~gavin/createpaymentrequest.php(源)

BitcoinJ https://bitcoinj.github.io/payment-protocol#introduction

另见附注

Javascript对象签名和加密工作组:http://datatracker.ietf.org/wg/jose/

维基百科的发票页面:http://en.wikipedia.org/wiki/Invoice特别是电子发票标准清单

sipa的付款协议建议:https://gist.github.com/1237788

ThomasV的“签名别名”提案:http://ecdsa.org/bitcoin_URIs.html

同态付款地址和付款合同协议:http://arxiv.org/abs/1212.3257

参考资料

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:501381次
    • 积分:7648
    • 等级:
    • 排名:第3088名
    • 原创:284篇
    • 转载:13篇
    • 译文:3篇
    • 评论:68条
    博客专栏
    微信订阅号
    欢迎加入QQ群
    玩家老黄历(微信小程序)
    谢谢支持~
    最新评论