The Uniform Resources specification is a method for encoding structured binary data in plain-text strings that are also well-formed URIs. It's usable with any binary data, but was developed with Bitcoin and other cryptocurrencies in mind.
To be precise, Uniform Resources (URs) include:
- A standard way to wrap CBOR-encoded data structures in a URI.
- A standard way to type the data in the URI so that it is self-describing.
- A standard way split and sequence longer messages.
- Optimizations for efficiency when URs are presented as QR codes.
URs are a crucial element of the Gordian architecture, allowing for the self-identified encoding of a variety of cryptographic data. This has been widely adopted for use in PSBTs and is also avialable for many other types of data such as seeds, keys, and shards, all listed in a registry of data types. It's optimized for airgapped usage and allows for standardized interoperability for Bitcoin apps released by different companies.
💡 URs are used widely in our Gordian reference apps, but our community members have focused most on UR's sequencing feature to create animated QRs that support PSBTs. URs can do a lot more: they can support any airgapped Bitcoin function and more than that, can support data encoding and storage for a large number of decentralized technologies whether it's airgapped or not.
We are well aware of the dangers of competing standards:
However, we believe that the UR specification serves enough real purposes to make the introduction of a new specification worthwhile:
- It's self-identifying. We saw different methodologies for transfering keys such as
xpub
,ypub
, andzpub
proliferating and thus causing confusion. Worse, they created layer violations by mixing encoding and policy. We wanted to create a specification with more clearly defined layers that could be expandable, yet still self-identify its contents. - It's focused on security. The transfer of key material between devices is a prime point of vulnerability, and so URs do their best to minimize that danger, ideally by supporting the transmission of those keys (and seeds and other private information) in an airgapped fashion.
- It integrates with QRs. While QR codes themselves are standard, the data encoded within QR codes is not, resulting in inconsistent usage among developers. We designed URs to resolve these interoperability issues by creating a standardized method for encoding binary data using CBOR and by specifying how to sequence larger binary encoding (as version 40 QR codes max out at 2,953 bytes).
- It focuses on the multisig experience. We see multisig as the future of Bitcoin, allowing for the creation of independent and resilient cryptocurrency addresses. Previous specifications are locked into the single-sig paradigm, while URs include specifications for a variety of data types crucial to multisig use.
You can't ever be certain that a network or serial interface between two devices won't lead to one of those devices corrupting the other. Nor can you be certain that a networked connection is proof from man-in-the-middle attacks. That leads to the need for airgaps, where devices don't physically connect except "through a gap of air". In recent years, QR codes have been a prime method of bridging airgaps: they leverage the cameras and displays in the devices to communicate. Airgaps can also be bridged by NFCs, MicroSDs, and other methods that remove the real-time interactivity of a networked connection.
URs are generally important for any type of interoperability between devices, because their self-identifications makes it easy for a receiving device to know what they're getting. However, they're particularly important when QRs are being used to communicate through an airgap, because of UR's support for QRs and particularly for Animated QRs.
Blockchain Commons' development of airgap specifications is not just the product of our work, but also cooperation with other Bitcoin wallet companies to create digital formats, specifications, and reference apps that support new ways to protect your digital assets. This discussion happens primarily in the Gordian Developer Community.
As detailed in the UR specification, URs are binary data that is represented with CBOR using a minimal canonical representation, converted to minimal bytewords, and prefaced with the UR type.
Thus the process encoding a UR, which is largely automated by Blockchain Commons libraries, is:
- Refer to the Registry of Uniform Resource Types for how to represent the desired data.
- Refer to the CBOR RFC for how to encode the data. In particular, be aware of how to use Canonical CBOR, how to encode major types, and how to encode byte strings.
- The CBOR reference is the best place to read about CBOR encoding, but be aware that whenever you encode something, you will typically preface data with one or more bytes showing data type and length; and as required you may also tag data (which is data type #6).
- Convert your complete CBOR binary representation to Bytewords using the minimal encoding. This is the first and last letters of the byteword, and will be done automatically if you are using the Blockchain Commons bytewords library and request
minimal
encoding - Prefix your UR with
ur:type/
, or in the case of a part of a sequenceur:type:sequence/
. Again, this will be done automatically if you use a Blockchain Commons UR Library.
For example:
- Seed: 59F2293A5BCE7D4DE59E71B4207AC5D2
- CBOR: A1015059F2293A5BCE7D4DE59E71B4207AC5D2
ur:crypto-seed
is defined as a map which must include the seed and which may include other data such as creation date.- The CBOR breaks down into
A1-01-50-59F2293A5BCE7D4DE59E71B4207AC5D2
. A1
represents a map of length 1.- That's major type 5 (for a map), which is represented as
101
in the most significant three bits, plus a length of 1, which is represented as00001
in the least significant three bits, or overall0b10100001
, which is0xA1
.
- That's major type 5 (for a map), which is represented as
01
represents item 1 in the map.50
represents a 16-byte byte-string payload.- That's major type 2 (for a byte string), which is represented as
010
, plus a payload of 16 bytes, or10000
, or overall0b01010000
, which is0x50
.
- That's major type 2 (for a byte string), which is represented as
59F2293A5BCE7D4DE59E71B4207AC5D2
represents the byte payload.
- Bytewords: obey acid good hawk whiz diet fact help taco kiwi gift view noon jugs quiz crux kiln silk tied help yell jade data
obey
(0xA1
) throughtied
(0xd2
) represent the CBOR data, whilehelp yell jade data
are checksums.
- Bytewords Minimal: oyadgdhkwzdtfthptokigtvwnnjsqzcxknsktdhpyljeda
- UR: ur:crypto-seed/oyadgdhkwzdtfthptokigtvwnnjsqzcxknsktdhpyljeda
Any data can be encoded as URs as long as it has a CBOR encoding and a user-defined UR type. The Registry of Uniform Resource types lists data types that Blockchain Commons specifies, maintains, and promotes. You can also define proprietary user-defined types.
To date, the major uses have fallen into three categories:
- PSBT Signing. URs can transfer PSBTs as they are being signed (
ur:crypto-psbt
). - Key Transfer. URs can be encode seeds (
ur:crypto-seed
), HD keys, (ur:crypto-hdkey
), and SSKR shards (ur:crypto-sskr
). - SSKR Shares. URs can encode shards of a key or seed sharded by SSKR.
When data is being transferred between airgapped apps, it often is done as part of a request (ur:crypto-request
) / response (ur:crypto-response
) interaction, as defined in BCR-2021-001.
Obviously, the most important tool is the CBOR reference.
CBOR has a more human-readable text diagnostic notation you should become familiar with. When you are testing your understanding of how CBOR encoding works or debugging, you can use the CBOR Playground to transform CBOR between hex and diagnostic notation, or if you prefer a command-line implementation, the CBOR-cli, which can be installed with npm
if you have Node.js installed.
Specifications for CBOR structures are written in the Concise Data Defintion Language (CDDL).
The bytewords CLI can also be of use, since CBOR is converted to bytewords for text encoding when constructing URs.
- A Guide to Using URs for PSBTs [our biggest success story]
- A Guide to Using URs for Key Material
- A Guide to Using URs for SSKR
- A Guide to Using URs for Request & Response
- List of UR Implementations
See the crypto-commons bc-ur
entry for the most up-to-date listing of reference libraries.
Current implementations of UR include C++, Java, Python, Rust, and Swift.
URs allow for standardized transfer of data across an airgap, including animated QRs for PSBTs, and URIs or QRs for a variety of other cryptodata. They can make the transfer of some of the most vulnerable cryptodata not just standardized and thus interoperable, but also secure.