UR と CBOR の入門
BitTool Signer が読み書きする QR コードは、プレーンなアドレスと PSBT テキストを除き、すべて Uniform Resource(BCR-2020-005)です。UR を自前で実装する必要はありませんが(ライブラリを使ってください)、各層を理解しておくとデバッグがずっと楽になります。
CBOR から QR テキストへ
CBOR bytes
→ append CRC-32 (4 bytes)
→ Bytewords "minimal": each byte becomes 2 letters (first + last letter of a 4-letter word)
→ "ur:" + type + "/" + bytewords single part
たとえば、短い EVM 署名のレスポンスは次のとおりです。
ur:eth-signature(1 パート)
UR:ETH-SIGNATURE/OEADTPDAGDHECKNDDWKIFTGLJLLEBDCEDPFMGWHTADAOHDFPJNBYWYMUYLLTIMKSWDCFWKYTSPVWGYVEGMDNJNWMLSGAOLHGDPATJEGLIOTOQZFPJNQDYNMHQDESRSIHLEHHLGDRTDYLHHUREYGMWTLBMWBKLFCTIHRKJZRHCKMSLFOYADCWJNLUAY
テキストは大文字小文字を区別しません。QR コードにする前に大文字に変換してください。そうすると文字が QR の 英数字 モードに収まり、バイトモードよりはるかに高密度になります。
マルチパート(アニメーション)UR
ペイロードが 1 つの QR コードに収まらない場合、エンコーダーはペイロードを等しい長さのフラグメントに分割し、複数のパートを生成します。
ur:<type>/<seq>-<count>/<bytewords of CBOR [seq, count, message-length, checksum, fragment]>
- パート
1…countは、フラグメントを順番どおりに運びます(「純粋な」パート)。 countより後のパートは ファウンテン パートです。seqとチェックサムから導出したシードに基づいて擬似ランダムに選んだフラグメントの XOR になっています。デコーダーはこれらから欠けたフラグメントを復元できます。count、message-length、checksum(メッセージ全体の CRC-32)は、1 つのセッション内のすべてのパートで同じです。BitTool Signer は、2 つのセッションが混在したスキャンを拒否します。
実務上の注意点:
- パートは順不同でスキャンし、重複は無視します。
- 表示側:最初の
count個のパートを繰り返し再生するのではなく、ループ内でnextPart()を使ってパートを生成し続けます。 - フラグメントサイズは、QR の密度とフレーム数のトレードオフです。BitTool Signer は、ウォレットレベルのペアリングに 400 バイト、署名レスポンスに 180 バイトを使っています。
ウォレットレベルのペアリング QR コードのフレーム 1:
ur:bytes、4 パート中の 1
UR:BYTES/1-4/LPADAACFAMCECYJYHYKIWKHKADLTHKAMCFOLIEJNJLIEIHIEIYKPJZJZIOJTIHJYKTJLJPJEIOJNHSINJTJTIHJYIOKOIHJPJKINJLJTADISHSIAIAJLKPJTJYJKLTONIEKSJOKPIDKSJLKSJOKPIDENFXHSJYHGIEINHTINJLIEJNGOIHGHFYJOETGSGHECJLJPETJTJNIDGRGLIAKPKKKOKNEMHGKKJEJKHFFGJEGRFWEEGMFDKTFXFYEOHDKKKPKOGDFEIDKOJSFPGYHKEOJPFPGDJKISHGIAGTGSJLGDEYIYGTFGGTGRFDGDGEEEHTIHHTHDHKHFGOISGSKOEHHFGTJPIMGDFXEMGDHGENHFIHIAISHSINJTIAIDJYIAIYIEIHJPINKOIHOEIYIAISHSJTIOIHIAEHDLDRIOJPIHIAIHINKOIHIADYDLDRIYJKIAJPINJOJYIYJOEYKTJOJEISJEHSIAIAJLKPJTJYGDHSJYISJEJNDLETEEDIDLDYDIDLDYDIONIEKSJOKPIDKSJLKSJOKPIDENFWIOFWIOJKIHJKJOHGKOFEGMFGEOGSFDGYKPENFXJTJSIEKOIYFEKOJYGTIAGYIMHKJPIAGMKNKSECEOGYGEIMGUKSHSJPIMEYHSIYHKHGIAGSJYIHJLFLHFJEKKEMFYEOGOGRFYGDESGYKKJPGSJOJPGYEOHFFXFEFXJLHKEEESKKIYIEFYFEFDFLFXJYGTGTIMESEYJOGMIHGOJKGYIHIAISHSINJTIAIDJYIAIYIEIHJPINKOIHOEIYIAISHSJTIOIHUYSWLYTA
これらのペイロードで使われる CBOR
使われるのは CBOR のごく一部だけです。
| メジャータイプ | 用途 |
|---|---|
| 0 unsigned int | マップのキー、データタイプ、チェーン ID、フィンガープリント、パスのインデックス |
| 2 byte string | 署名データ、鍵、チェーンコード、署名、PSBT |
| 3 text string | Origin、名前、ペアリングマップのキーと値 |
| 4 array | パスの要素、ディスクリプタのリスト、ペアリングのアカウント |
| 5 map | すべてのリクエスト、レスポンス、鍵の構造 |
| 6 tag | 型付きアイテム(後述) |
| 7 simple | true / false(is-private、強化フラグ) |
リクエストは 確定長 を使い、マップのキーに重複がなく、末尾に余分なバイトがあってはなりません。浮動小数点数、負の整数、不定長アイテムは、これらの構造のどこにも登場しません。
タグ
| タグ | 名前 | 包む対象 |
|---|---|---|
| 37 | uuid | リクエスト ID のバイト列 |
| 303 | crypto-hdkey | HD キーのマップ |
| 304 | crypto-keypath | パスのマップ {1: components, 2: source-fingerprint, 3: depth} |
| 305 | crypto-coin-info | {1: coin type, 2: network} |
| 400 | script-hash | sh(…) |
| 401 | witness-script-hash | wsh(…) |
| 403 | public-key-hash | pkh(…) |
| 404 | witness-public-key-hash | wpkh(…) |
| 409 | taproot | tr(…) |
バイト文字列とテキストの区別は重要です。リクエスト ID は、UUID のテキストではなく、タグ 37 内のバイト列です。キー 6 の EVM アドレスは、"0x…" ではなく 20 バイトの生データです。
リクエストを手作業で読む
EIP-1559 の例 の CBOR に注釈を付けたものです。
a7 map, 7 entries
01 d8 25 50 5f1e9b2c…5a01 1: tag 37 (uuid), 16 bytes
02 58 31 02ef010c…80c0 2: 49 bytes: 0x02 ‖ rlp(unsigned EIP-1559 tx)
03 04 3: data-type 4
04 01 4: chain-id 1
05 d9 0130 a2 5: tag 304 (crypto-keypath), map 2
01 8a 18 2c f5 18 3c f5 00 f5 00 f4 00 f4 components [44,true,60,true,0,true,0,false,0,false]
02 1a 73c5da0a source-fingerprint 0x73c5da0a
06 54 9858effd…eda94 6: 20-byte address
07 6e "BitTool Wallet" 7: origin
同じバイト列の全体
a701d825505f1e9b2c7d3a4e6f8a0b1c2d3e4f5a0102583102ef010c843b9aca008506fc23ac0082520894000000000000000000000000000000000000dead872386f26fc1000080c00304040105d90130a2018a182cf5183cf500f500f400f4021a73c5da0a06549858effd232b4033e47d90003d41ec34ecaeda94076e426974546f6f6c2057616c6c6574
ライブラリ
| 言語 | UR | CBOR |
|---|---|---|
| JavaScript / TypeScript | @ngraveio/bc-ur。型付きクラスには Keystone の @keystonehq/bc-ur-registry* | cborg |
| Swift | URKit | URKit の DCBOR、SwiftCBOR |
| Kotlin / Java | Hummingbird | Hummingbird、com.upokecenter:cbor |
| Rust | ur | minicbor、ciborium |