Uniform Resources (URs) allow for the encoding of self-describing, structured binary data in text strings that can are optimized for transmission in QR Codes. The types of data that Blockchain Commons has specified for URs appear in Registry of UR Types and include a variety of key material including seeds, keys, and BIP-39 mnemonics. (SSKR shards can also be encoded as URs.)
Key material is the most valuable data in a cryptography system because private keys and the seeds from which they are derived control cryptocurrency, verify identity, and serve other crucial purposes. For this reason it should be carefully secured — if possible with airgapping, where the material is held in some non-networked place. That’s where URs come in. They allow key material to be encoded as URs, converted into QRs, and then transmitted across an airgap in a way that’s safe and secure, minimizing its vulnerability at the time when it’s the most vulnerable.
The above image, drawn from an interoperability demo for LetheKit and
Gordian Cosigner shows
how an xpub
and an xprv
can be transmitted between airgapped
devices using standardized, typed URs.
The following major categories of key material are available as URs: seeds, HD keys, and BIP 39 words.
Why Use URs for Key Material?
Why use URs for your key material when you could pass bare seeds, the
mnemonic words themselves, or xprvs
and xpubs
for HD keys?
The biggest reason is interoperability. URs are all self-identifying, so you always know exactly what you’re getting. They’re also built to be encoded into QRs, which is a great way to transfer data across airgaps. The result is an easy, safe way to transfer key material and to expect that it will be understood by products produced by a variety of other manufacturers.
This is particularly important for key material because, as noted earlier, it is both the core of controlling cryptocurrency (and other digital assets) and uniquely vulnerable to theft or loss.
- By using a system that integrates well with airgaps, you can maximize the safety of key material without potentially falling prey to man-in-the-middle attacks and you can simultaneously maintain the security of airgapped devices.
- By using a self-describing, interoperable method to store key material, you can ensure that it will remain well-understood and thus usable far into the future, not becoming muddled with the huge variety of standards for key material that could otherwise result in it becoming effectively unsuable if a user has no idea what it is.
Key Material: crypto-seed
A seed is the basis of a Bitcoin account. It’s typically generated by a wallet, or alternatively a seed generator such as Blockchain Commons’ LetheKit or seedtool.
A Simple Seed
The example uses Blockchain Commons’ default 128-bit seed, YINMN BLUE.
HEX: 59f2293a5bce7d4de59e71b4207ac5d2
BIP-39 WORDS: fly mule excess resource treat plunge nose soda reflect adult ramp planet
BYTEWORDS: hawk whiz diet fact help taco kiwi gift view noon jugs quiz crux kiln silk tied omit keno lung jade
GORDIAN ENVELOPE: See QR code, above
SEGWIT UR OUTPUT DESCRIPTOR: ur:output-descriptor/oeadisktjojeisdefzdydtaolytantjloxaxhdclaxvlcprfttldjobkredtlnhsidwybaeyjtswyandlgjnehtkdsidbkqzsrkphyfhsaaahdcxhnfgnepefxgdytryckticelyotsstoknfntavevaskiddmolsarntykbrybtjpksamtantjooeadlncsghykaeykaeykaocyhngrmuwzaycyzssajpsndifmkohy
SEGWIT TEXT OUTPUT DESCRIPTOR: wpkh([604b93f2/84'/0'/0']xpub6DVfq9VduocgjGeR69Nyr8CCi9w5gywnU7wXMYGswpHjffjcbLYNzz6G6555VDcSZLDwZPzJHJQabVWWgkpvYntpunL3UjHGrkCJ6VndbQf)#ncwysjuk
Do not use this seed to hold real monies; they could disappear immediately!
A simple, unadorned seed looks like this:
59F2293A5BCE7D4DE59E71B4207AC5D2
As discussed in the UR Overview, this seed can be converted to the CBOR A1015059F2293A5BCE7D4DE59E71B4207AC5D2
and then a ur:crypto-seed
:
ur:crypto-seed/oyadgdhkwzdtfthptokigtvwnnjsqzcxknsktdhpyljeda
Decoding a Simple Seed
The Bytewords and CBOR apps demonstrate how this seed can then be broken down into its constituent parts.
The bytewords CLI can be used to convert the Bytewords minimal encoding used in URs to CBOR:
$ bytewords -i minimal -o hex OYADGDHKWZDTFTHPTOKIGTVWNNJSQZCXKNSKTDHPYLJEDA
a1015059f2293a5bce7d4de59e71b4207ac5d2
The CBOR CLI can then be used to decode the result, revealing a map with just one item, which is the seed itself:
$ cbor2diag -x a1015059f2293a5bce7d4de59e71b4207ac5d2
{1: h'59f2293a5bce7d4de59e71b4207ac5d2'}
UR was built to support clean and efficient conversion into QR codes. That same seed can be encoded into a QR code as following:
If you read this with a QR reader you’ll get:
UR:CRYPTO-SEED/OYADGDHKWZDTFTHPTOKIGTVWNNJSQZCXKNSKTDHPYLJEDA
A Seed with Metadata
More complex examples of ur:crypto-seed
may incorporate a creation
date (map element #2, tagged 100), a name (map element #3), and/or a
note (map element #4) as detailed in the crypto-seed
CDDL.
The CBOR for a ur:crypto-seed
containing all of these elements could look like the following:
a4015059f2293a5bce7d4de59e71b4207ac5d202D8641A6092DC07036541636F726E046C436F66666565206D6F6E6579
This is a CBOR map containing four elements.
It breaks apart as shown:
A4 # map(4)
01 # element #1
50 # 16 bytes in length
59F2293A5BCE7D4DE59E71B4207AC5D2 # SEED
02 # element #2
D8 64 # tag(100) (date)
1A 6092DC07 # CREATION DATE (1620237319)
03 # element #3
65 # 5-character text
41636F726E # NAME ("Acorn")
04 # element #4
6C # 12-character text
436F66666565206D6F6E6579 # NOTE("Coffee money")
The CBOR-CLI can similarly be used to decode this information:
$ cbor2diag -x a4015059f2293a5bce7d4de59e71b4207ac5d202D8641A6092DC07036541636F726E046C436F66666565206D6F6E6579
{
1: h'59f2293a5bce7d4de59e71b4207ac5d2',
2: 100(1620237319),
3: "Acorn",
4: "Coffee money"
}
Using the Bytewords CLI you can convert the CBOR to minimal Bytewords:
$ bytewords -i hex -o minimal a4015059f2293a5bce7d4de59e71b4207ac5d202D8641A6092DC07036541636F726E046C436F66666565206D6F6E6579
oxadgdhkwzdtfthptokigtvwnnjsqzcxknsktdaotpiecyhnmouoataxihfpiajljpjtaajzfxjliyiyihihcxjnjljtihkkpseernwl
And you have a crypto-seed:
UR:CRYPTO-SEED/OXADGDHKWZDTFTHPTOKIGTVWNNJSQZCXKNSKTDAOTPIECYHNMOUOATAXIHFPIAJLJPJTAAJZFXJLIYIYIHIHCXJNJLJTIHKKPSEERNWL
Mnemonic Words: crypto-bip39
BIP39 details how mnemonic words can be used to define a master seed. These words can also be encoded for transportation using URs, as defined in the CDDL for BIP39.
The encoding is simple, requiring a map with an array of words and a language.
The test vector A2018C66736869656C646567726F75706565726F6465656177616B65646C6F636B6773617573616765646361736865676C6172656477617665646372657765666C616D6565676C6F76650262656E
demonstrates the usage:
cbor2diag -x A2018C66736869656C646567726F75706565726F6465656177616B65646C6F636B6773617573616765646361736865676C6172656477617665646372657765666C616D6565676C6F76650262656E
{
1:
[
"shield",
"group",
"erode",
"awake",
"lock",
"sausage",
"cash",
"glare",
"wave",
"crew",
"flame",
"glove"
],
2: "en"
}
Converting this to minimal bytewords results in:
ur:crypto-bip39/oeadlkiyjkisinihjzieihiojpjlkpjoihihjpjlieihihhskthsjeihiejzjliajeiojkhskpjkhsioihieiahsjkisihiojzhsjpihiekthskoihieiajpihktihiyjzhsjnihihiojzjlkoihaoidihjtrkkndede
Key Material: crypto-hdkey
HD Keys allow for a hierarchy of keys. Both master keys and derived keys can be encoded using URs, as described in the CDDL for hdkeys.
A Master Key
The following master HD key is derived from the seed 59F2293A5BCE7D4DE59E71B4207AC5D2
:
xprv9s21ZrQH143K4Mnjc7E8rpSMf8JB1XWmojYf7Ndk6zcNSbUYBsvTqJcdzTok1XwYcgytn5CRxtwhHu93NNXNQwGUbBqL3AHHZZrtKpEvmww
That Base58 xprv
decodes to hex as follows:
0488ade4000000000000000000b40359eb975b5e662298db589f75ed694b17755abbd0a230c24ffb8ac2be66fd0046f8a7a92fc3ca4fd4cbf3cb5bacde4356ce790e2cd6bc206ea2574ef8991318fe6a22e3
BIP32 reveals that this information is partitioned as follows:
- 04 ; version 4
- 88ade4 ;
xprv
- 00 ; depth 0 == master key
- 00000000 ; parent fingerprint
- 00000000 ; child number
- b40359eb975b5e662298db589f75ed694b17755abbd0a230c24ffb8ac2be66fd ; chain code
- 0046f8a7a92fc3ca4fd4cbf3cb5bacde4356ce790e2cd6bc206ea2574ef8991318 ; key data
- fe6a22e3 ; base58 checksum
Per the CDDL, creating the CBOR for this master key requires creating a map with 3 to 4 elements, which:
- identify the
hdkey
as a master key in map element #1; - optionally mark it as private in map element #2; and
- encode the key data and chain code in map elements #3 and #4.
The resulting CBOR is:
A401F502F50358210046F8A7A92FC3CA4FD4CBF3CB5BACDE4356CE790E2CD6BC206EA2574EF8991318045820B40359EB975B5E662298DB589F75ED694B17755ABBD0A230C24FFB8AC2BE66FD
This decodes as follows:
$ cbor2diag -x A401F502F50358210046F8A7A92FC3CA4FD4CBF3CB5BACDE4356CE790E2CD6BC206EA2574EF8991318045820B40359EB975B5E662298DB589F75ED694B17755ABBD0A230C24FFB8AC2BE66FD
{
1: true,
2: true,
3: h'0046f8a7a92fc3ca4fd4cbf3cb5bacde4356ce790e2cd6bc206ea2574ef8991318',
4: h'b40359eb975b5e662298db589f75ed694b17755abbd0a230c24ffb8ac2be66fd'
}
As usual, converting to Bytewords then allows creation of the UR:
$ bytewords -i hex -o minimal A401F502F50358210046F8A7A92FC3CA4FD4CBF3CB5BACDE4356CE790E2CD6BC206EA2574EF8991318045820B40359EB975B5E662298DB589F75ED694B17755ABBD0A230C24FFB8AC2BE66FD
oxadykaoykaxhdclaefgyaosptdlsrsggwtysbwfsbhppsuefxhftokkbadwtbrfcxjtoehgglyanlbwcsaahdcxqzaxhkwmmshphyiycpmkuyhdnekpweingrchkphtrktioedysagwzolesarniyzcrhdntkbb
The result is:
ur:crypto-hdkey/oxadykaoykaxhdclaefgyaosptdlsrsggwtysbwfsbhppsuefxhftokkbadwtbrfcxjtoehgglyanlbwcsaahdcxqzaxhkwmmshphyiycpmkuyhdnekpweingrchkphtrktioedysagwzolesarniyzcrhdntkbb
A Derived Key
A derived key will similarly include the key data and chain code, but
also tends to include a derivation path (map element #6) and a parent
fingerprint (map element #8) as described in the CDDL for
hdkeys. The
following test
vector
demonstrates these elements as well as coininfo
(map element #5) to
denote the key as testnet. Note that both the coininfo and the
derivation paths are defined with tags (305 and 304 respectively).
The following CBOR:
A5035821026FE2355745BB2DB3630BBC80EF5D58951C963C841F54170BA6E5C12BE7FC12A6045820CED155C72456255881793514EDC5BD9447E7F74ABB88C6D6B6480FD016EE8C8505D90131A1020106D90130A1018A182CF501F501F500F401F4081AE9181CF3
Breaks down as follows:
cbor2diag -x A5035821026FE2355745BB2DB3630BBC80EF5D58951C963C841F54170BA6E5C12BE7FC12A6045820CED155C72456255881793514EDC5BD9447E7F74ABB88C6D6B6480FD016EE8C8505D90131A1020106D90130A1018A182CF501F501F500F401F4081AE9181CF3
{
3: h'026fe2355745bb2db3630bbc80ef5d58951c963c841f54170ba6e5c12be7fc12a6',
4: h'ced155c72456255881793514edc5bd9447e7f74abb88c6d6b6480fd016ee8c85',
5: 305({2: 1}),
6: 304({1: [44, true, 1, true, 1, true, 0, false, 1, false]}),
8: 3910671603
}
The coininfo
element (#5) demonstrates use of the coininfo CDDL. Here, the network is set to testnet.
The key derivation
element (#6) demonstrates use of the keypath CDDL. Here, the derivation path is set to m/44'/1'/1'/0/1
.
The parent-fingerprint element (#8) is simply set to 3910671603
(or in hex: 1AE9181CF3
).
The resulting crypto-hdkey
after conversion to minimal Bytewords is:
ur:crypto-hdkey/onaxhdclaojlvoechgferkdpqdiabdrflawshlhdmdcemtfnlrctghchbdolvwsednvdztbgolaahdcxtottgostdkhfdahdlykkecbbweskrymwflvdylgerkloswtbrpfdbsticmwylklpahtaadehoyaoadamtaaddyoyadlecsdwykadykadykaewkadwkaycywlcscewfihbdaehn
Related Topics
A few other URs are related to key material:
- SSKR allows for the transmission of shares that are recombined to reconstruct key material.
- Envelope can store key material.
Each is covered in their own document.
Testing Key Material URs with Blockchain Commons’ Reference Tools
Blockchain Commons reference tools allow for experimentation with the UR format. The following examples use our seedtool, keytool, and the bytewords CLIs, as well as the CBOR cli.
The Seed
A seed can be generated with seedtool
:
$ seedtool
9c49536666b3f5cdbbe8d6da01aa6a66
$ seed=9c49536666b3f5cdbbe8d6da01aa6a66
Rather than outputting hex, seedtool can also output a UR for the crypto-seed
:
$ seedtool -i hex $seed -u
ur:crypto-seed/oyadgdnsgaguiyiyqdyksnrkvstbtnadpkimiybzrycyck
bytewords
can decode this output:
$ bytewords -i minimal -o hex oyadgdnsgaguiyiyqdyksnrkvstbtnadpkimiybzrycyck
a101509c49536666b3f5cdbbe8d6da01aa6a66
cbor2diag
then reveals the original seed within the CBOR encoding:
$ cbor2diag -x a101509c49536666b3f5cdbbe8d6da01aa6a66
{1: h'9c49536666b3f5cdbbe8d6da01aa6a66'}
The BIP39
seedtool
can also generate BIP39 words, in either mnemonic or UR format:
$ seedtool -i hex $seed -o bip39
ordinary enhance sunset sniff dismiss traffic use bracket sure ask once slot
$ seedtool -i hex $seed -o bip39 -u
ur:crypto-bip39/oyadlkisjljpieinjthsjpkkioihjtishsjtiaihiyjkkpjtjkihjyihjkjtiniyiyioieinjkjninjkjkiojyjphsiyiyiniaiakpjkihioidjphsiajeihjyiejkkpjpihiahsjkjeiejljtiaihiejkjzjljybyckylhl
Again, bytewords
and cbor2diag
can decode the UR:
$ bytewords -i minimal -o hex oyadlkisjljpieinjthsjpkkioihjtishsjtiaihiyjkkpjtjkihjyihjkjtiniyiyioieinjkjninjkjkiojyjphsiyiyiniaiakpjkihioidjphsiajeihjyiejkkpjpihiahsjkjeiejljtiaihiejkjzjljybyckylhl
a1018c686f7264696e61727967656e68616e63656673756e73657465736e696666676469736d69737367747261666669636375736567627261636b657464737572656361736b646f6e636564736c6f74
$ cbor2diag -x a1018c686f7264696e61727967656e68616e63656673756e73657465736e696666676469736d69737367747261666669636375736567627261636b657464737572656361736b646f6e636564736c6f74
{1:
["ordinary",
"enhance",
"sunset",
"sniff",
"dismiss",
"traffic",
"use",
"bracket",
"sure",
"ask",
"once",
"slot"]
}
The Master Key
keytool
supports key and address derivation. For example, it can produce a master xprv
from a seed:
$ keytool --seed $seed master-key-base58
xprv9s21ZrQH143K3zAmshnnUZcq8YF2GPBnf5C7DhH5Y3EEBbSQCoPTsG6kFCQDKm4qSopjFQnMWhPuytDxezCYir9hdwAWGmJfSxKdaZZPHxj
keytool
also can produce URs:
$ keytool --seed $seed master-key
ur:crypto-hdkey/oxadykaoykaxhdclaeswcspsndaezohttlpmfxdlqdcsaxfhuygwoteheylenbmolflninmsehmnhybdstaahdcxseoylrlbjkwmsfctzmetbyollbencftprprkswvwsrguesssnscxnbcftivsrlclbykiflbs
Again, you can decode that with bytewords
and cbor2diag
:
$ bytewords -i minimal -o hex oxadykaoykaxhdclaeswcspsndaezohttlpmfxdlqdcsaxfhuygwoteheylenbmolflninmsehmnhybdstaahdcxseoylrlbjkwmsfctzmetbyollbencftprprkswvwsrguesssnscxnbcftivsrlclbykiflbs
a401f502f503582100c618ac9b00fb5ad5ad432fb318033fdb4fa331328aa09282866997318e5e0bc7045820c1a1847f73ebcc1fff3811a67f3619d8b6bbc6e5c35339c49c20a019d0e8b721
$ cbor2diag -x a401f502f503582100c618ac9b00fb5ad5ad432fb318033fdb4fa331328aa09282866997318e5e0bc7045820c1a1847f73ebcc1fff3811a67f3619d8b6bbc6e5c35339c49c20a019d0e8b721
{
1: true,
2: true,
3: h'00c618ac9b00fb5ad5ad432fb318033fdb4fa331328aa09282866997318e5e0bc7',
4: h'c1a1847f73ebcc1fff3811a67f3619d8b6bbc6e5c35339c49c20a019d0e8b721'
}
A Derived Key
keytool
can also create derived keys. The following example produced an xprv
and a UR for the 44’/1’/1’/0/1 keypath:
$ /usr/local/bin/keytool --master-key xprv9s21ZrQH143K3zAmshnnUZcq8YF2GPBnf5C7DhH5Y3EEBbSQCoPTsG6kFCQDKm4qSopjFQnMWhPuytDxezCYir9hdwAWGmJfSxKdaZZPHxj --full-address-derivation-path m/44h/1h/1h/0/1 address-key-base58 address-key
xprvA3px5eB5pEbMi5bApo1CcoLeXHMubgFJ8hedudWE3gdMeHP6FQYXNJpPxcuznwE4PBHRcEodyp7ykLKvvpCrDK6zTLMBG899dnHTzJ3aKty
ur:crypto-hdkey/onaoykaxhdclaeknidehqdwsatwppfcfdklatdmkuyknckurlgnssrihsgdytniscntkwpcxsrmsnlaahdcxsazshllbztynlufnskreoefgdsztchihttnsahlkamlbcningefhnsjekoutyllkamoeadlecsdwykadykadykaewkadwkaocyahhfespfaycyrnnneooebkadltsn
The following shows the same for the xpub
:
$ /usr/local/bin/keytool --master-key xprv9s21ZrQH143K3zAmshnnUZcq8YF2GPBnf5C7DhH5Y3EEBbSQCoPTsG6kFCQDKm4qSopjFQnMWhPuytDxezCYir9hdwAWGmJfSxKdaZZPHxj --full-address-derivation-path m/44h/1h/1h/0/1 address-pub-key-base58 address-pub-key
xpub6GpJV9hyec9evZfdvpYCywHP5KCQ18y9VvaEi1uqc2ALX5iEnwrmv78sotc3ZhwnSw1mvu437TsZ31mCwxMenzVpXsjtsB5UUaKMsYxexnG
ur:crypto-hdkey/oxaxhdclaottglktmoaoaerhonbygygejzzmhphfwnvaprjsfwfhdwsfvytpcxfxvavthkdiplaahdcxsazshllbztynlufnskreoefgdsztchihttnsahlkamlbcningefhnsjekoutyllkamoeadlecsdwykadykadykaewkadwkaocyahhfespfaycyrnnneooetldprhne
Here’s the decoding of that xprv
:
$ bytewords -i minimal -o hex onaoykaxhdclaeknidehqdwsatwppfcfdklatdmkuyknckurlgnssrihsgdytniscntkwpcxsrmsnlaahdcxsazshllbztynlufnskreoefgdsztchihttnsahlkamlbcningefhnsjekoutyllkamoeadlecsdwykadykadykaewkadwkaocyahhfespfaycyrnnneooebkadltsn
a502f5035821007a6231b3ef07ecb0192480d298db7a1edf8d9cc365ca30da6823cfec20c39799045820c2fa5d7ffcf68b3cc5b5a24626fc1765d19c058c067f23694a3f9c6b76ddf78c06a2018a182cf501f501f500f401f4021a055639b0081abe9e33a2
$ cbor2diag -x a502f5035821007a6231b3ef07ecb0192480d298db7a1edf8d9cc365ca30da6823cfec20c39799045820c2fa5d7ffcf68b3cc5b5a24626fc1765d19c058c067f23694a3f9c6b76ddf78c06a2018a182cf501f501f500f401f4021a055639b0081abe9e33a2
{
2: true,
3: h'007a6231b3ef07ecb0192480d298db7a1edf8d9cc365ca30da6823cfec20c39799',
4: h'c2fa5d7ffcf68b3cc5b5a24626fc1765d19c058c067f23694a3f9c6b76ddf78c',
6: {1: [44, true, 1, true, 1, true, 0, false, 1, false], 2: 89536944},
8: 3198038946
}
Similarly, here’s the decoded xpub
:
{
3: h'02d14e77920200b9a511514a6cff5b56f1e6b271423f2ccce1d82043e6e05927ae',
4: h'c2fa5d7ffcf68b3cc5b5a24626fc1765d19c058c067f23694a3f9c6b76ddf78c',
6: {1: [44, true, 1, true, 1, true, 0, false, 1, false], 2: 89536944},
8: 3198038946
}
Integrating Key Material URs Into Your Code
You can incorporate URs into your own code using bc-ur for C++ or through conversions of that library to other languages such as Java and Swift.
bc-ur provides access to objects such as UREncoder
, URDecoder
, and
Bytewords
, which support many of the same functions as described
here for the command line. They can also be used with other Blockchain
Commons Crypto Commons Reference Libraries which
support a variety of cryptography functions.
UR Libraries
Language | Repo | Contributor | Status |
---|---|---|---|
C++ | bc-ur | Blockchain Commons | |
Java | bc-ur-java | Bitmark | |
Java | Hummingbird | Craig Raw | |
Python | foundation-ur-py | Foundation | |
Rust | bc-ur-rust | Blockchain Commons | |
Rust | ur-rust | Dominik Spicher | |
Swift | URKit + URUI | Blockchain Commons | |
TypeScript | bc-ur for TS | xardass |
Conclusion
Key material can be transferred using ur:crypto-seed
,
ur:crypto-bip39
, and ur:crypto-hdkey
. Doing so allows you to use
airgaps, which increase the safety of these vulnerable operations; and
also increases your interoperability, so that other software can work
with you, and so that your key material remains usable far into the
future.