ERC-4527: 适用于钱包的二维码传输协议
钱包和离线签名器之间的二维码数据传输协议。
Authors | Aaron Chen (@aaronisme), Sora Lee (@soralit), ligi (@ligi), Dan Miller (@danjm), AndreasGassmann (@andreasgassmann), xardass (@xardass), Lixin Liu (@BitcoinLixin) |
---|---|
Created | 2021-12-07 |
Discussion Link | https://ethereum-magicians.org/t/add-qr-code-scanning-between-software-wallet-cold-signer-hardware-wallet/6568 |
Table of Contents
摘要
此 EIP 的目的是提供一种通过二维码在离线签名器和仅观察钱包之间进行处理和数据传输的协议。
动机
越来越多的用户喜欢使用完整的离线签名器来管理他们的私钥,例如硬件钱包和处于离线模式的手机。为了签署交易或数据,这些离线签名器必须依赖仅观察钱包,因为它会准备要签名的数据。目前,离线签名器和仅观察钱包之间有 4 种可能的数据传输方法:二维码、USB、蓝牙和文件传输。与其他三种方法相比,二维码数据传输方法具有以下优点:
- 透明性和安全性:与 USB 或蓝牙相比,用户可以通过二维码轻松解码数据(在一些工具的帮助下)。它还可以帮助用户清楚地识别他们将要签名的内容,从而提高透明度,从而提高安全性。
- 改进的兼容性:与 USB 和蓝牙相比,二维码数据传输具有更广泛的兼容性。通常,它不会因浏览器升级、系统升级等软件更改而中断。
- 改进的用户体验:与 USB、蓝牙和文件传输相比,二维码数据传输可以提供更好的用户体验,尤其是在用户使用移动设备时。
- 更小的攻击面:USB 和蓝牙比二维码具有更大的攻击面。
由于这些优点,二维码数据传输是更好的选择。不幸的是,目前对于离线签名器应如何与仅观察钱包一起工作以及应如何编码数据,没有现代标准。 此 EIP 提出了一种标准流程和数据传输协议,供离线签名器与仅观察钱包一起使用。
规范
离线签名器:离线签名器是一种持有用户私钥且无法访问网络的设备或应用程序。
仅观察钱包:仅观察钱包是一种可以访问网络并且可以与以太坊区块链交互的钱包。
流程
为了与离线签名器一起使用,仅观察钱包应遵循以下流程。
- 离线签名器通过二维码向仅观察钱包提供公钥信息,以生成地址、同步余额等。
- 仅观察钱包生成未签名的数据并通过二维码将其发送到离线签名器进行签名,数据可以包括交易、类型化数据等。
- 离线签名器对数据进行签名,并通过二维码向仅观察钱包提供签名。
- 仅观察钱包接收签名,构建已签名数据(交易)并执行以下活动,例如广播交易等。
数据传输协议
由于单个二维码只能包含有限数量的数据,因此应利用动画二维码进行数据传输。BlockchainCommons
发布了一系列称为 Uniform Resources (UR) 的数据传输协议。它提供了一种将数据编码为动画二维码的基本方法。此 EIP 将使用 UR 并扩展其当前定义。
Concise Binary Object Representation(CBOR)
将用于二进制数据编码。Concise Data Definition Language(CDDL)
将用于表达 CBOR。
使用离线签名器设置仅观察钱包
为了允许仅观察钱包从以太坊区块链收集信息,离线签名器需要将公钥提供给仅观察钱包,钱包将使用这些公钥来查询以太坊区块链中的必要信息。
在这种情况下,离线签名器应提供扩展的公钥和推导路径。UR 类型称为 crypto-hdkey
将用于编码此数据,并且推导路径将被编码为 crypto-keypath
。
密钥路径的 CDDL
crypto-keypath
将用于指定密钥路径。以下规范以 Concise Data Definition Language(CDDL) 编写,用于 crypto-key-path
; 密钥推导路径的元数据。
;
; `source-fingerprint`(如果存在)是从中推导出关联密钥的祖先密钥的指纹。
;
; 如果 `components` 为空,则 `source-fingerprint` 必须是主密钥的指纹。
;
; `depth`(如果存在)表示关联密钥路径中推导步骤的数量,即使它不存在于此结构的 `components` 元素中。
crypto-keypath = {
components: [path-component], ; 如果为空,则必须存在 source-fingerprint
? source-fingerprint: uint32 .ne 0 ; 祖先密钥的指纹,如果 components 为空,则为主密钥的指纹
? depth: uint8 ; 如果这是直接从主密钥派生的公钥,则为 0
}
path-component = (
child-index / child-index-range / child-index-wildcard-range,
is-hardened
)
uint32 = uint .size 4
uint31 = uint32 .lt 2147483648 ;0x80000000
child-index = uint31
child-index-range = [child-index, child-index] ; [low, high] where low < high
child-index-wildcard = []
is-hardened = bool
components = 1
source-fingerprint = 2
depth = 3
扩展公钥的 CDDL
由于目的是传输公钥数据,因此 crypto-hdkey
的定义将仅保留用于公钥用途。
以下规范以 Concise Data Definition Language CDDL
编写,并包括上面的 crypto-keypath 规范。
; hd-key 必须是派生密钥。
hd-key = {
derived-key
}
; 派生密钥必须是公共的,具有可选的链码,并且
; 可以携带有关其使用和推导的其他元数据。
; 为了保持与 [BIP32] 的同构并允许从此密钥推导密钥,`chain-code`、`origin` 和 `parent-fingerprint` 必须存在。
; 如果 `origin` 仅包含一个推导步骤并且还包含 `source-fingerprint`,
; 则 `parent-fingerprint` 必须与 `source-fingerprint` 相同,或者可以省略。
derived-key = (
key-data: key-data-bytes,
? chain-code: chain-code-bytes ; 如果不能从此密钥派生更多密钥,则省略
? origin: #6.304(crypto-keypath), ; 密钥的推导方式
? name: text, ; 此密钥的简称。
? source: text, ; 此密钥的设备信息或任何其他描述
)
key-data = 3
chain-code = 4
origin = 6
name = 9
source = 10
uint8 = uint .size 1
key-data-bytes = bytes .size 33
chain-code-bytes = bytes .size 32
如果提供了链码,则可以使用它来派生子密钥,但如果未提供,它只是一个单独的密钥,并且可以提供来源来指示推导密钥路径。
如果签名者出于任何原因想要提供多个公钥而不是扩展公钥,则签名者可以使用 crypto-account
。
将未签名的数据从仅观察钱包发送到离线签名器
为了将未签名的数据从仅观察钱包发送到离线签名器,将引入新的 UR 类型 eth-sign-request
来编码签名请求。
Eth Sign Request(以太坊签名请求) 的 CDDL。
以下规范以 Concise Data Definition Language CDDL
编写。
此规范中的 UUID 使用 #6.37 标记的 CBOR 二进制字符串表示 UUID,根据 IANA CBOR Tags Registry
。
; 以太坊签名请求的元数据。
;
sign-data-type = {
type: int .default 1 transaction data; 未签名的数据类型
}
eth-transaction-data = 1; 未签名事务数据的旧式事务 rlp 编码
eth-typed-data = 2; EIP-712 类型签名数据
eth-raw-bytes=3; 用于签名消息的使用方法,如 EIP-191 personal_sign 数据
eth-typed-transaction=4; EIP-2718 未签名事务数据的类型化事务
; 以太坊签名请求的元数据。
; request-id: 此签名请求的标识符。
; sign-data: 未签名的数据
; data-type: 请参阅 sign-data-type 定义
; chain-id: 链 ID 定义请参阅 https://github.com/ethereum-lists/chains 了解详细信息
; derivation-path: 用于签署数据的私钥的密钥路径
; address: 用于验证目的的签名类型的以太坊地址(可选)
eth-sign-request = (
sign-data: sign-data-bytes, ; sign-data 是要由离线签名器签名的数据,目前它可以是未签名交易或类型化数据
data-type: #3.401(sign-data-type),
chain-id: int .default 1,
derivation-path: #5.304(crypto-keypath), ; 用于签署此请求的密钥路径
?request-id: uuid, ; 此签名请求的 uuid
?address: eth-address-bytes, ; 签名密钥地址的验证目的
?origin: text ; 此签名请求的来源,如钱包名称
)
request-id = 1
sign-data = 2
data-type = 3
chain-id = 4 ; 它将是以太坊相关区块链的链 ID
derivation-path = 5
address = 6
origin = 7
eth-address-bytes = bytes .size 20
sign-data-bytes = bytes ; 对于未签名交易,它将是未签名交易数据的 rlp 编码,对于 ERC 712 类型化数据,它将是 json 字符串的字节。
离线签名器提供给仅观察钱包的签名
数据签名后,离线签名器应将签名发回给仅观察钱包。此处引入了称为 eth-signature
的新 UR 类型来编码此数据。
Eth Signature(以太坊签名) 的 CDDL。
以下规范以 Concise Data Definition Language CDDL
编写。
eth-signature = (
request-id: uuid,
signature: eth-signature-bytes,
? origin: text, ; 用于提供此签名的设备信息
)
request-id = 1
signature = 2
origin = 3
eth-signature-bytes = bytes .size 65; 签名请求的签名 (r,s,v)
基本原理
此 EIP 使用了一些现有的 UR 类型,如 crypto-keypath
和 crypto-hdkey
,并且还引入了一些新的 UR 类型,如 eth-sign-request
和 eth-signature
。以下是我们选择 UR 作为二维码数据传输协议的原因:
UR 为二维码数据传输提供了坚实的基础
- 使用字母数字二维码模式提高效率。
- 在每个部分中包含整个消息的 CRC32 校验和,以将二维码的不同部分连接在一起,并确保已重建传输的消息。
- 使用
Fountain Code
来处理任意数量的数据,这些数据可以是最小的、有限的部分序列,也可以是不确定的部分序列。Fountain Code
最终可以帮助接收者更容易地进行数据提取。
UR 为新用途提供了现有的有用类型和可扩展性
目前,UR 已经提供了一些现有类型,如 crypto-keypath
和 crypto-hdkey
,因此很容易为新用途添加新类型和定义。
UR 拥有活跃的气隙钱包社区。
目前,UR 拥有一个活跃的 airgapped wallet community
,该社区不断改进 UR。
向后兼容性
目前,没有现有协议来定义通过二维码进行数据传输,因此目前无需解决向后兼容性问题。
测试用例
测试用例可以在 Keystone 团队发布的 ur-registry-eth
包中找到。
参考实现
参考实现可以在 Keystone 团队发布的 ur-registry-eth
包中找到。
安全考虑事项
离线签名器应解码 eth-sign-request
中的所有数据,并在签名之前将其显示给用户以进行确认。建议在 eth-sign-request
中提供一个地址字段。如果提供,离线签名器应验证该地址是否与与签名密钥关联的地址相同。
版权
根据 CC0 放弃版权和相关权利。
Citation
Please cite this document as:
Aaron Chen (@aaronisme), Sora Lee (@soralit), ligi (@ligi), Dan Miller (@danjm), AndreasGassmann (@andreasgassmann), xardass (@xardass), Lixin Liu (@BitcoinLixin), "ERC-4527: 适用于钱包的二维码传输协议 [DRAFT]," Ethereum Improvement Proposals, no. 4527, December 2021. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-4527.