The purpose of this EIP is to provide a process and data transmission protocol via QR Code between offline signers and watch-only wallets.
There is an increasing number of users whom like to use complete offline signers to manage their private keys, signers like hardware wallets and mobile phones in offline mode. In order to sign transactions or data, these offline signers have to rely on a watch-only wallet since it would prepare the data to be signed. Currently, there are 4 possible data transmission methods between offline signers and watch-only wallets: QR Code, USB, Bluetooth, and file transfer. The QR Code data transmission method have the following advantages when compared to the other three methods mentioned above:
Due to these advantages, QR Code data transmissions is a better choice. Unfortunately, there is no modern standard for how offline signers should work with watch-only wallets nor how data should be encoded. This EIP presents a standard process and data transmission protocol for offline signers to work with watch-only wallets.
Offline signer: An offline signer is a device or application which holds the user’s private keys and does not have network access.
Watch-only wallet: A watch-only wallet is a wallet that has network access and can interact with the Ethereum blockchain.
In order to work with offline signers, the watch-only wallet should follow the following process.
Since a single QR Code can only contain a limited amount of data, animated QR Codes should be utilized for data transmission. The BlockchainCommons
have published a series of data transmission protocol called Uniform Resources (UR). It provides a basic method to encode data into animated QR Codes. This EIP will use UR and extend its current definition.
Concise Binary Object Representation(CBOR)
will be used for binary data encoding. Concise Data Definition Language(CDDL)
will be used for expressing the CBOR.
In order to allow a watch-only wallet to collect information from the Ethereum blockchain, the offline signer would need to provide the public keys to the watch-only wallet in which the wallet will use them to query the necessary information from the Ethereum blockchain.
In such a case, offline signers should provide the extended public keys and derivation path. The UR Type called crypto-hdkey
will be used to encode this data and the derivation path will be encoded as crypto-keypath
.
The crypto-keypath
will be used to specify the key path.The following specification is written in Concise Data Definition Language(CDDL) for crypto-key-path
; Metadata for the derivation path of a key.
;
; `source-fingerprint`, if present, is the fingerprint of the
; ancestor key from which the associated key was derived.
;
; If `components` is empty, then `source-fingerprint` MUST be a fingerprint of
; a master key.
;
; `depth`, if present, represents the number of derivation steps in
; the path of the associated key, even if not present in the `components` element
; of this structure.
crypto-keypath = {
components: [path-component], ; If empty, source-fingerprint MUST be present
? source-fingerprint: uint32 .ne 0 ; fingerprint of ancestor key, or master key if components is empty
? depth: uint8 ; 0 if this is a public key derived directly from a master key
}
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
Since the purpose is to transfer public key data, the definition of crypto-hdkey
will be kept only for public key usage purposes.
The following specification is written in Concise Data Definition Language CDDL
and includes the crypto-keypath spec above.
; An hd-key must be a derived key.
hd-key = {
derived-key
}
; A derived key must be public, has an optional chain code, and
; may carry additional metadata about its use and derivation.
; To maintain isomorphism with [BIP32] and allow keys to be derived from
; this key `chain-code`, `origin`, and `parent-fingerprint` must be present.
; If `origin` contains only a single derivation step and also contains `source-fingerprint`,
; then `parent-fingerprint` MUST be identical to `source-fingerprint` or may be omitted.
derived-key = (
key-data: key-data-bytes,
? chain-code: chain-code-bytes ; omit if no further keys may be derived from this key
? origin: #6.304(crypto-keypath), ; How the key was derived
? name: text, ; A short name for this key.
? source: text, ; The device info or any other description for this key
)
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
If the chain-code is provided, then it can be used to derive child keys but if it isn’t provided, it is simply a solo key and the origin can be provided to indicate the derivation key path.
If the signer would like to provide multiple public keys instead of the extended public key for any reason, the signer can use crypto-account
for that.
To send the unsigned data from a watch-only wallet to an offline signer, the new UR type eth-sign-request
will be introduced to encode the signing request.
The following specification is written in Concise Data Definition Language CDDL
.
UUIDs in this specification notated UUID are CBOR binary strings tagged with #6.37, per the IANA CBOR Tags Registry
.
; Metadata for the signing request for Ethereum.
;
sign-data-type = {
type: int .default 1 transaction data; the unsigned data type
}
eth-transaction-data = 1; legacy transaction rlp encoding of unsigned transaction data
eth-typed-data = 2; EIP-712 typed signing data
eth-raw-bytes=3; for signing message usage, like EIP-191 personal_sign data
eth-typed-transaction=4; EIP-2718 typed transaction of unsigned transaction data
; Metadata for the signing request for Ethereum.
; request-id: the identifier for this signing request.
; sign-data: the unsigned data
; data-type: see sign-data-type definition
; chain-id: chain id definition see https://github.com/ethereum-lists/chains for detail
; derivation-path: the key path of the private key to sign the data
; address: Ethereum address of the signing type for verification purposes which is optional
eth-sign-request = (
sign-data: sign-data-bytes, ; sign-data is the data to be signed by offline signer, currently it can be unsigned transaction or typed data
data-type: #3.401(sign-data-type),
chain-id: int .default 1,
derivation-path: #5.304(crypto-keypath), ;the key path for signing this request
?request-id: uuid, ; the uuid for this signing request
?address: eth-address-bytes, ;verification purpose for the address of the signing key
?origin: text ;the origin of this sign request, like wallet name
)
request-id = 1
sign-data = 2
data-type = 3
chain-id = 4 ;it will be the chain id of ethereum related blockchain
derivation-path = 5
address = 6
origin = 7
eth-address-bytes = bytes .size 20
sign-data-bytes = bytes ; for unsigned transactions it will be the rlp encoding for unsigned transaction data and ERC 712 typed data it will be the bytes of json string.
After the data is signed, the offline signer should send the signature back to the watch-only wallet. The new UR type called eth-signature
is introduced here to encode this data.
The following specification is written in Concise Data Definition Language CDDL
.
eth-signature = (
request-id: uuid,
signature: eth-signature-bytes,
? origin: text, ; The device info for providing this signature
)
request-id = 1
signature = 2
origin = 3
eth-signature-bytes = bytes .size 65; the signature of the signing request (r,s,v)
This EIP uses some existing UR types like crypto-keypath
and crypto-hdkey
and also introduces some new UR types like eth-sign-request
and eth-signature
. Here are the reasons we choose UR for the QR Code data transmission protocol:
Fountain Code
for the arbitrary amount of data which can be both a minimal, finite sequence of parts and an indefinite sequence of parts. The Fountain Code can ultimately help the receiver to make the data extraction easier.Currently, UR has provided some existing types like crypto-keypath
and crypto-hdkey
so it is quite easy to add a new type and definitions for new usages.
Currently, the UR has an active airgapped wallet community
which continues to improve the UR forward.
Currently, there is no existing protocol to define data transmissions via QR Codes so there are no backward compatibility issues that needs to be addressed now.
The test cases can be found on the ur-registry-eth
package released by the Keystone team.
The reference implementation can be found on the ur-registry-eth
package released by the Keystone team.
The offline signer should decode all the data from eth-sign-request
and show them to the user for confirmation prior to signing. It is recommended to provide an address field in the eth-sign-request
. If provided, the offline signer should verify the address being the same one as the address associated with the signing key.
Copyright and related rights waived via CC0.