---
# System prepended metadata

title: UCAN flavored CACAO

---

# UCAN flavored CACAO

## Background

- A CACAO is a container for a capability chain.
	- A capability can be represented as IPLD object.
	- Full capability chain can be easily transferred.
- UCAN is a capability format based on JWS.
	- Serialization of a capability chain requires multiple rounds of serialization/deserialization.

## Hypotheses

- UCAN can be wrapped in a CACAO container
- UCAN can add JSON canonicalization of some form

## Technical details


CACAO supports two types of designators:


- `$.h.t` - type of a payload,
- `$.s.t` - type of a signature.

Currently `$.h.t` is `eip4361`only. `$.s.t` can be `eip191` for Ethereum EOA or `eip1271` for Ethereum contract wallet based on EIP-1271.

UCAN mandates two similar fields. `$.signatures[0].header.ucv` specifies payload type. `$.signatures[0].header.typ` and `$.signatures[0].header.alg` along with the general implicit shape of JWS imply type of a signature.

So, we can specify a UCAN flavour of CACAO the following way:


- `$.h.t` is `ucv@0.8.1` or similar to indicate type of a payload compatible with UCAN spec,
- `$.s.t` is `JWT` to indicate JWS signature suite used,
- `$.s.m` contains then UCAN header fields, except `typ` and `ucv`.

### Conversion operations


**UCAN-flavored-CACAO to UCAN**


1. Prepare header
	1. `{"typ": $.s.t, "ucv": replace($.h.t, 'ucv@')}`
	2. merge with `$.s.m`
2. Prepare signature
	1. it is `base64url($.s.s)`
3. Prepare payload
	1. it is `$.p`
	2. **ISSUE** There is a canonicalization problem inherent in most JWS implementations, including current UCANs. A payload encoded as base64url as well as a signature change based on order of JSON properties. CACAO uses IPLD serialization which is comptible to present efforts to add native JSON canonicalization. Yet, this is a point of divergence.

**UCAN to UCAN-flavored-CACAO**


1. Prepare header:
	1. `$.h.t = ucv@0.8.1`
2. Prepare signature:
	1. `$.s.t = "JWT"`
	2. `$.s.m = remove(signatures[0].headers, 'ucv', 'typ')`
	3. `$.s.s = bytes(signatures[0].signature)`
3. Prepare payload:
	1. `$.p = payload`

### Non-canonicalized version

UCAN inherits JWT feature of being sensitive to a raw JSON representation. Spaces, key duplication, unsorted keys all affect the bytes actually signed. The conversion above is only suitable for a canonicalized UCAN, with spaces removed, and keys sorted and deduplicated. Non-canonicalized UCAN can not be properly reconstructed from IPLD data structure. We should somehow preserve the original JWT bytes then.

One way is to store raw JWT bytes on IPLD. Then, at runtime, we can decide how to parse it based on the contents.

Another way is to incorporate raw bytes of non-canonicalized signature payload, i.e. header and payload as a field in signature meta property.

## Capability chain


As CACAO is serialized as a container, we could pass around all the referenced capabilities inside the same CACAO container, that is a CAR file, as separate IPLD records. This way we avoid double encoding (i.e. flattened JWS included in another flattened JWS) when including proofs to UCAN.

## Example of interoperability


SIWE -> CACAO -> UCAN

A user logs into an application via SIWE prompt. The SIWE prompt contains a resource `wnfs://alice.example.com/pictures/?can=wnfs/APPEND`.

The SIWE is wrapped in CACAO towards ephemeral application key, `did:key`. Then this `did:key` delegates wnfs access towards a 3rd party backend as UCAN.
