README.md

# CID

An Elixir implementation of [Content Identifiers (CIDs)](https://github.com/multiformats/cid) — self-describing, content-addressed identifiers used throughout the IPFS and IPLD ecosystems.

A CID bundles together a version indicator, a content type codec, and a multihash of the content into a single identifier. Given a CID and the original content, anyone can verify that the content matches the identifier.

## CID Versions

**CIDv0** is the legacy format: a bare base58btc-encoded SHA-256 multihash, always 46 characters starting with `"Qm"`. Content type is implicitly `dag-pb`.

**CIDv1** is the self-describing format: a multibase-encoded binary containing the version varint, content codec varint, and multihash. The multibase prefix character identifies the string encoding.

## Usage

### Creating CIDs

```elixir
# CIDv1 with defaults (raw content type, sha2-256, base32)
cid = CID.create("hello world")
cid.cid_string
# => "bafkreifzjut3te2nhyekklss27nh3k72ysco7y32koao5eei66wof36n5e"

# CIDv1 with custom options
cid = CID.create("hello world",
  content_type: "dag-cbor",
  hash_algorithm: "sha3-256",
  base: :base58btc
)

# CIDv0
cid = CID.create_v0("hello world")
cid.cid_string
# => "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"
```

### Parsing CIDs

```elixir
# Parse any CID string (v0 or v1, any multibase)
{:ok, cid} = CID.parse("bafkreifzjut3te2nhyekklss27nh3k72ysco7y32koao5eei66wof36n5e")
cid.version        # => 1
cid.content_type   # => "raw"
cid.hash_algorithm # => "sha2-256"
cid.hash_digest    # => <<185, 77, 39, ...>>

# Raising variant
cid = CID.parse!("QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4")
cid.version        # => 0
```

### Parsing CIDs from raw bytes

For binary formats like CAR files, parse a CID from raw bytes and get back the remaining data:

```elixir
{:ok, cid, rest} = CID.from_bytes(binary_data)
```

### Verifying content

Check that content matches a CID's hash:

```elixir
cid = CID.create("hello world")
CID.verify(cid, "hello world")    # => :ok
CID.verify(cid, "wrong content")  # => :mismatch
```

### Converting between representations

```elixir
# Struct to string
CID.cid_string(cid)
"#{cid}"  # String.Chars protocol is implemented

# Struct to raw bytes (no multibase encoding)
CID.to_bytes(cid)
```

### Introspection

```elixir
CID.valid?("bafkreifzjut3te...")  # => true
CID.valid?("not a cid")          # => false

CID.is_v0?(cid)  # works on structs and strings
CID.is_v1?(cid)
CID.v0?("QmaozN...")  # string-only check
```

## The CID struct

```elixir
%CID{
  version: 0 | 1,
  content_type: "raw" | "dag-cbor" | "dag-pb" | ...,
  hash_algorithm: "sha2-256" | "sha3-256" | ...,
  hash_size: 32,
  hash_digest: <<...>>,       # raw hash bytes
  multihash: <<...>>,         # codec-prefixed hash with length
  cid_bytes: <<...>>,         # full CID binary (no multibase)
  cid_string: "bafkrei..."   # multibase-encoded string
}
```

## Dependencies

This library builds on top of three sibling multiformats libraries:

- [multicodec](https://github.com/tyler-eon/multicodec) — codec identification and the central multiformats registry
- [multibase](https://github.com/tyler-eon/multibase) — base encoding/decoding
- [multihash](https://github.com/tyler-eon/multihash) — hash algorithm identification and digest wrapping

## Part of the multiformats ecosystem

For runtime codec registration and cross-component composition, see the [multicodec](https://github.com/tyler-eon/multicodec) project.