iroh & IPFS

Iroh is an IPFS system. It uses content identifiers (CIDs). Content addressing is a powerful primitive that belongs at the foundation of the internet.

Iroh is not an IPFS implementation. An implementation of IPFS should be able to interoperate with kubo the reference implementation of nearly all IPFS Specs. Iroh can interoperate with kubo by bridging the two technologies, but by default one shouldn't expect to be able to add content to kubo and get it out with iroh, or vice versa.

Why not just make iroh an IPFS implementation?

At first, we did! We wrote a ground-up implementation of IPFS in rust called Beetle. We switched away because Iroh has different design goals than IPFS, and after writing an implementation, we realized couldn't achieve those goals & keep the implementation 'badge'. Iroh aims to be the smallest working foundation for building apps with sublinear scaling. The word small is the challenging one here. IPFS is designed to upgrade the entire web. To do that it has to accommodate numerous use cases and requirements that we couldn't build into iroh while keeping the project small.

Comparison Table

Here's a quick rundown on some of the core technical distinctions between IPFS & iroh:

CID UsageUsed for root hashes on the Blob layerUsed for all blocks
Hash FunctionBLAKE3Various, SHA2 by default
Maximum Block Sizenone1MiB
Data LayoutKey-ValueDirected Acyclic Graphs (DAGs)
Data Model"Bring your own"IPLD or "Bring your own"
SyncingDocument Layernone
Networking StackConnection Layerlibp2p
Public Key CryptographyED25519 KeysVarious, ED25519 by default
Naming systemnoneIPNS, DNSLink
Content StorageUser Files + CacheInternal Repository
Verification Checkpointssend and receivereceive

CID Interop

If you create a file that is less than 256Kib, kubo can be configured to emit the same content:

# configure IPFS to use the BLAKE3 hash algorithm, and wrap in a directory to match iroh's default behaviour
$ ipfs add file.txt --hash blake3 --wrap-with-directory
added bafkr4ig4ljhnxasawambeqcsymycobuw7ftxdjr3iusquxax2maa5artku file.txt
added bafyb4ig2hp3tqb762mg7bvuixfimok7tyn4a3b3vswlkvcphppj7j2pemi

$ iroh add file.txt
Adding file.txt as /Users/b5/file.txt...
- /Users/b5/file.txt: 12B bafkr4ig4ljhnxasawambeqcsymycobuw7ftxdjr3iusquxax2maa5artku
Total: 12B

Collection: bafkr4iatacaewbfgoqe7d4mcxtuhfxbbog57t7xpvppqgvyr2bzswlb4fy

The CID for file.txt in both systems is bafkr4ig4ljhnxasawambeqcsymycobuw7ftxdjr3iusquxax2maa5artku. The collection CIDs are different because directories work differently, but this small overlap between iroh & IPFS forms a foundation we can build all sorts of interop from.

If we create a file that's larger than 256Kb, however, things break down:

# create a random 1M file
$ head -c 1000000 </dev/urandom > file

$ ipfs add --hash blake3 --wrap-with-directory file.txt
added bafyb4idt2x6f35tsvvkic3uxn5377gvjohpu7ejlxjdgno73lb4yzwrca4 file
added bafyb4ia4lras4leu2lwpc57lg3xk2c4bdacabuzpunbjrl7piwug4lojiq

$ iroh add file
Adding file as /Users/b5/code/
- /Users/b5/code/ 976.56 KiB bafkr4ihr5vpp33v5ufos2dneywofls3gx67b5jmraxcn77odsu3yqcsohq
Total: 976.56 KiB

Collection: bafkr4id2xleuzonckwul47dwmaktqw6dgpudvfzmdxkitv6qmg7bwxy7hu

This is because under the hood IPFS is cutting the input file up into blocks of data so that each block can be incrementally verified during transfer. Iroh does not do this, and so the hashes are different. To address this, we need CID translation.

CID Translation

CID translations are signed documents that state a content equivelancy between hashes in two different systems. Here's what a CID translation would look like for the random 1M file example above, expressed in JSON:

  "eq": {
    "iroh": "bafkr4ihr5vpp33v5ufos2dneywofls3gx67b5jmraxcn77odsu3yqcsohq",
    "kubo": "bafyb4idt2x6f35tsvvkic3uxn5377gvjohpu7ejlxjdgno73lb4yzwrca4"
  "author": "3pwjma35aeu7mmmjolslefpnlsdztyp4zwf4zwx32nnvlmzko4aa",
  "signature": "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

In english this would read "author 3pwjma35... has said this iroh CID and that kubo CID are equal content. They point to the same bytes".

Using translations requires trusting the author of the translation. The "author" field is an iroh public key, which can be used to verify the signature field. The signature is the contents of the "eq" object.

Interop anchors have configuration settings to automatically publish content the anchor has to kubo. As of now publishing to kubo only works on 1Mb files. We plan to implement both large file publishing and fetching in the future.