# Delegated IPNS with UCANs ## Problem [IPNS publishing protocol] requires updates to be signed by the private key corresponding to the name (public) key. Which makes it incompatible with capability delegation provided by UCANs. Specifically if Alice generated keypair `(An, As)` and wanted to let Bob publish (IPNS) updates for `Aa` IPNS key, she would have to share `As` private key (otherwise Bob would not be able to create valid update records), which in turn would prevent `Alice` from limiting or revoking `Bob` ability to update the key. ## Goals We would like to provide IPNS feature in web3.storage such that: 1. Alice could delegate (and revoke) publishing capability to Bob (via UCANs). 2. Does not require Alice surrendring their private key to either Bob or our service. 3. Alice could switch service provider and retain full control of the IPNS key. 4. Alice IPNS key should not get compromised even if web3.storage is. ### Approach We could meet all the above listed requirements by introducing extra layer of inderecation: 1. Alice's client can generate "mirroring" keypair `(Mn, Ms)` along with `(An, As)`. 1. Alice could generate IPNS publish record for `An` with value `/ipns/Mn`. 1. Alice client can delegate "IPNS mirrong" capability with web3.storage by sharing: - IPNS update record `/ipns/${An} -> /ipns/${Mn}` - `Ms` secret key encrypting it with web3.storage's public key. 1. web3.storage could (re)publish `/ipns/${An} -> /ipns/${Mn}` record. 1. Alice could delegate [name publishing][name publishing protocol] capability to Bob without sharing any keys. 1. Bob could send [name publishing][name publishing protocol] invocation to web3.storage service _(providing proof of Alice's delegation via UCAN)_. 1. web3.storage can validate Bob's proof and generate IPNS update record `/ipns/${Mn}/ -> /ipfs/${cid}` and publish to DHT & ipfs pubsub. - web3.storage could create such record since Alice shared `Ms` key. After following steps take place resolution would work as expected: `/ipns/${An} -> /ipns/${Mn} -> /ipfs/${cid}` Also note that since Alice has not shared `As` key, Alice is able to revoke web3.storage's ability to update `/ipns/${An}` record by publishing IPNS record replacing `/ipns/${Mn}` value. This way Alice can switch service provider and/or rotate `${Mn}` key in the event if `${Ms}` is compromised. :::warning It is worth calling out that large TTL in IPNS record creates an attac vector for adversory in posetion of compromised `Ms` key. Adversory could republish `/ipns/${An} -> /ipns/${Mn}` until it expires and in combination with `Ms` could effectively pointing `/ipns/${An}` to any CID to fragment of the network that has not seen Alice's newer update to `/ipns/${An}` In other words `Alice` would have to find a right balance between flexibility and risks that come with it when choosing TTL. ::: ### Future Plans Implementing and deploying such a srevice creates an opportunity for us to test out delegated [name publishing][name publishing protocol] using UCANs. We will take these learning to propose IPNS protocol extension which would remove need for layer of inderecation and reduce surface for described attack vector. ## Other considerations #### Key custody It may seem that web3.storage would need to take extra steps to ensure that private keys (like `Ms`) shared with service aren't compromised. In practice however it just needs to maintain only own private key (corresponding to it's `did:key:*`) as it could derive `Ms` from the combination of delegated "IPNS mirrong" cability and own private key. #### [BIP 32][] BIP 32 key derivation algorithm had been considered as an alternative to mirroring key pair generation, however that would limit number of possible keys and would make key rotaion more difficult. On the other hand clint library could simply abstract secondary keypair generation and would also Allow alice to retain `Ms`. [IPNS Publishing protocol]:https://github.com/ipfs/specs/blob/master/IPNS.md [name publishing protocol]:https://hackmd.io/@gozala/pins [BIP 32]:https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki