From 70f039a6548f3a93f0afe3157ab77103629ec77f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Wed, 29 Oct 2025 15:48:15 +0100 Subject: [PATCH] update Readme --- Readme.md | 5 +- pkg/container/Readme.md | 2 + pkg/container/SPEC.md | 109 ---------------------------------------- 3 files changed, 4 insertions(+), 112 deletions(-) delete mode 100644 pkg/container/SPEC.md diff --git a/Readme.md b/Readme.md index 8d3ac91..753bb40 100644 --- a/Readme.md +++ b/Readme.md @@ -41,6 +41,7 @@ The UCAN specification is separated in multiple sub-spec: - [Main specification](https://github.com/ucan-wg/spec) - [Delegation](https://github.com/ucan-wg/delegation/tree/v1_ipld) - [Invocation](https://github.com/ucan-wg/invocation) +- [Container](https://github.com/ucan-wg/container) Not implemented yet: - [Revocation](https://github.com/ucan-wg/revocation/tree/first-draft) @@ -53,11 +54,9 @@ Not implemented yet: ## Status -`go-ucan` currently support the required parts of the UCAN specification: the main specification, delegation and invocation. +`go-ucan` currently support the required parts of the UCAN specification: the main specification, delegation and invocation. It leverages the sibling project [`go-did-it`](https://github.com/MetaMask/go-did-it) for easy and extensible DID support. Besides that, `go-ucan` also includes: -- a simplified [DID](https://www.w3.org/TR/did-core/) and [did-key](https://w3c-ccg.github.io/did-method-key/) implementation -- a [token container](https://github.com/ucan-wg/go-ucan/tree/v1/pkg/container) with CBOR and CAR format, to package and carry tokens together, see [SPEC](pkg/container/SPEC.md) - support for encrypted values in token's metadata ## Getting Help diff --git a/pkg/container/Readme.md b/pkg/container/Readme.md index 176358b..c2692ea 100644 --- a/pkg/container/Readme.md +++ b/pkg/container/Readme.md @@ -1,5 +1,7 @@ # Token container +The specification has been promoted to https://github.com/ucan-wg/container. + ## Why do I need that? Some common situation asks to package multiple tokens together: diff --git a/pkg/container/SPEC.md b/pkg/container/SPEC.md deleted file mode 100644 index b0b971c..0000000 --- a/pkg/container/SPEC.md +++ /dev/null @@ -1,109 +0,0 @@ -# UCAN container Specification v0.1.0 - -## Editors - -* [Michael Muré], [Consensys] - -## Authors - -* [Michael Muré], [Consensys] -* [Hugo Dias] - -## Language - -The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP 14] when, and only when, they appear in all capitals, as shown here. - -# 0 Abstract - -[User-Controlled Authorization Network (UCAN)][UCAN] is a trustless, secure, local-first, user-originated authorization and revocation scheme. This document describes a container format for transmitting one or more UCAN tokens as bytes, regardless of the transport. - -# 1 Introduction - -The UCAN spec itself is transport agnostic. This specification describes how to transfer one or more [UCAN] tokens bundled together, regardless of the transport. - -# 2 Container format - -## 2.1 Inner structure - -UCAN tokens, regardless of their kind ([Delegation], [Invocation], [Revocation], [Promise]) MUST be first signed and serialized into DAG-CBOR bytes according to their respective specification. As the token's CID is not part of the serialized container, any CID returned by this operation is to be ignored. - -All the tokens' bytes MUST be assembled in a [CBOR] array. The ordering of tokens in the array MUST NOT matter. This array SHOULD NOT have duplicate entries. - -That array is then inserted as the value under the `ctn-v1` string key, in a CBOR map. There MUST NOT be other keys. - -For clarity, the CBOR shape is given below: - -```json -{ - "ctn-v1": [ - , - , - , - ] -} -``` - -## 2.2 Serialisation - -To serialize the container into bytes, the inner CBOR structure MUST then be serialized into bytes according to the CBOR specification. The resulting bytes MAY be compressed by a supported algorithm, then MAY be encoded with a supported base encoding. - -The following compression algorithms are REQUIRED to be supported: -- [GZIP] - -The following base encoding combinations are REQUIRED to be supported: -- base64, standard alphabet, padding -- base64, URL alphabet, no padding - -The CBOR bytes MUST be prepended by a single byte header to indicate the selected combination of base encoding and compression. This header value MUST be set according to the following table: - -| Header as hex | Header as ASCII | Base encoding | Compression | -|---------------|-----------------|-------------------------|----------------| -| 0x40 | @ | raw bytes | no compression | -| 0x42 | B | base64 std padding | no compression | -| 0x43 | C | base64 url (no padding) | no compression | -| 0x4D | M | raw bytes | gzip | -| 0x4F | O | base64 std padding | gzip | -| 0x50 | P | base64 url (no padding) | gzip | - -For clarity, the resulting serialisation is in the form of `
`. - -# 3 FAQ - -## 3.1 Why not include the UCAN CIDs? - -Several attacks are possible if UCAN tokens aren't validated. If CIDs aren't validated, at least two attacks are possible: [privilege escalation] and [cache poisoning], as UCAN delegation proofs depends on a correct hash-linked structure. - -By not including the CID in the container, the recipient is forced to hash (and thus validate) the CIDs for each token. If presented with a claimed CID paired with the token bytes, implementers could ignore CID validation, breaking a core part of the proof chain security model. Hash functions are very fast on a couple kilobytes of data so the overhead is still very low. It also significantly reduces the size of the container. - -## 3.2 Why compress? Why not always compress? - -Compression is a relatively demanding operation. As such, using it is a tradeoff between size on the wire and CPU/memory usage, both when writing and reading a container. The transport itself can make compression worthwhile or not: for example, HTTP/2 and HTTP/3 headers are already compressed, but HTTP/1 headers are not. This being highly contextual, the choice is left to the final implementer. - -# 4 Implementation recommendations - -## 4.1 Dissociate reader and writer - -While it is tempting to write a single implementation to read and write a container, it is RECOMMENDED to separate the implementation into a reader and a writer. The writer can simply accept arbitrary tokens as bytes, while the reader provides a read-only view with convenient access functions. - -# 5 Acknowledgments - -Many thanks to all the [Fission] team and in particular to [Brooklyn Zelenka] for creating and pushing [UCAN] and other critical pieces like [WNFS], and generally being awesome and supportive people. - - - -[BCP 14]: https://www.rfc-editor.org/info/bcp14 -[Brooklyn Zelenka]: https://github.com/expede -[CBOR]: https://www.rfc-editor.org/rfc/rfc8949.html -[Consensys]: https://consensys.io/ -[Delegation]: https://github.com/ucan-wg/delegation/tree/v1_ipld -[Fission]: https://fission.codes -[GZIP]: https://datatracker.ietf.org/doc/html/rfc1952 -[Hugo Dias]: https://github.com/hugomrdias -[Invocation]: https://github.com/ucan-wg/invocation -[Michael Muré]: https://github.com/MichaelMure/ -[Promise]: https://github.com/ucan-wg/promise/tree/v1-rc1 -[Revocation]: https://github.com/ucan-wg/revocation/tree/first-draft -[UCAN]: https://github.com/ucan-wg/spec -[WNFS]: https://github.com/wnfs-wg -[cache poisoning]: https://en.wikipedia.org/wiki/Cache_poisoning -[privilede escalation]: https://en.wikipedia.org/wiki/Privilege_escalation