multiformats.cid

Implementation of the CID spec.

This module differs from other modules of multiformats, in that the functionality is completely encapsulated by a single class CID, which is imported from top level instead of the module itself:

>>> from multiformats import CID

CID

class CID(base, version, codec, digest)[source]

Bases: object

Container class for Content IDentifiers.

CIDs can be explicitly instantiated by passing multibase, CID version, multicodec and multihash digest to the constructor:

>>> cid = CID("base58btc", 1, "raw",
... "12206e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95")
>>> str(cid)
'zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA'

Alternatively, a pair of multihash codec and raw hash digest can be passed in lieu of the multihash digest:

>>> raw_digest = bytes.fromhex(
... "6e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95")
>>> cid = CID("base58btc", 1, "raw", ("sha2-256", raw_digest))
>>> str(cid)
'zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA'

The multihash digest and raw digest values can be passed either as bytes-like objects or as the corresponding hex strings:

>>> isinstance(raw_digest, bytes)
True
>>> raw_digest.hex()
'6e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95'

Note: the hex strings are not multibase encoded.

Calling bytes on an instance of this class returns its binary representation, as a bytes object:

>>> cid = CID("base58btc", 1, "raw",
... "12206e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95")
>>> raw_digest.hex()
        '6e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95'
>>> bytes(cid).hex()
'015512206e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95'
#^^   0x01 = CIDv1
#  ^^ 0x55 = 'raw' codec
>>> bytes(cid)

The digest parameter can be specified in the following ways:

  • as a str, in which case it is treated as a hex-string and converted to bytes using bytes.fromhex

  • as a BytesLike, in which case it is converted to bytes directly

  • as a pair (multihash_codec, raw_digest) of a multihash and raw hash digest, which are used to produce a multihash digest via the wrap metho

If digest is specified by a pair, the multihash_codec value can be specified in the following ways:

  • by multihash multicodec name, as a str

  • by multihash multicodec code, as a int

  • as a Multihash object

If digest is specified by a pair, the raw_digest value can be specified in the following ways:

Parameters:
  • base (str or Multibase) – default multibase to use when encoding this CID

  • version – the CID version (0 or 1)

  • codec (str, int or Multicodec) – the content multicodec

  • digest – the content multihash digest, or a pair of multihash codec and raw content digest (see below)

Raises:
  • ValueError – if the CID version is unsupported

  • ValueError – if version is 0 but base is not ‘base58btc’ or codec is not ‘dag-pb’

  • KeyError – if the multibase, multicodec or multihash are unknown

property base

Multibase used to encode the CID:

  • if a CIDv1 was decoded from a multibase-encoded string, the encoding multibase is used

  • if a CIDv1 was decoded from a bytestring, the ‘base58btc’ multibase is used

  • for a CIDv0, ‘base58btc’ is always used

Example usage:

>>> s = "zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA"
>>> cid = CID.decode(s)
>>> cid.base
Multibase(name='base58btc', code='z',
          status='default', description='base58 bitcoin')
Return type:

Multibase

property codec

Codec that the multihash digest refers to.

Example usage:

>>> s = "zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA"
>>> cid = CID.decode(s)
>>> cid.codec
Multicodec(name='raw', tag='ipld', code='0x55',
           status='permanent', description='raw binary')
Return type:

Multicodec

static decode(cid)[source]

Decodes a CID from a bytestring or a multibase-encoded string.

Example usage for CIDv1 multibase-encoded string:

>>> s = "zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA"
>>> CID.decode(s)
CID('base58btc', 1, 'raw',
'12206e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95')

Example usage for CIDv1 bytestring (multibase always set to ‘base58btc’):

>>> b = bytes.fromhex(
... "015512206e6ff7950a36187a801613426e85"
... "8dce686cd7d7e3c0fc42ee0330072d245c95")
>>> CID.decode(b)
CID('base58btc', 1, 'raw',
'12206e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95')

Example usage for CIDv0 base58-encoded string:

>>> s = "QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"
>>> CID.decode(s)
CID('base58btc', 0, 'dag-pb',
'1220c3c4733ec8affd06cf9e9ff50ffc6bcd2ec85a6170004bb709669c31de94391a')

Example usage for CIDv0 bytestring (multibase always set to ‘base58btc’):

>>> b = bytes.fromhex(
... "1220c3c4733ec8affd06cf9e9ff50ffc6b"
... "cd2ec85a6170004bb709669c31de94391a")
>>> CID.decode(b)
CID('base58btc', 0, 'dag-pb',
'1220c3c4733ec8affd06cf9e9ff50ffc6bcd2ec85a6170004bb709669c31de94391a')
Parameters:

cid (str or BytesLike) – the CID bytes or multibase-encoded string

Raises:
  • ValueError – if the CID is malformed or the CID version is unsupported

  • KeyError – if the multibase, multicodec or multihash are unknown

Return type:

CID

property digest

Multihash digest.

Example usage:

>>> s = "zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA"
>>> cid = CID.decode(s)
>>> cid.digest.hex()
'12206e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95'
Return type:

bytes

encode(base=None)[source]

Encodes the CID using a given multibase. If None is given, the CID’s own multibase is used by default.

Example usage:

>>> s = "zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA"
>>> cid = CID.decode(s)
>>> cid.encode() # default: cid.base
'zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA'
>>> cid.encode("base32")
'bafkreidon73zkcrwdb5iafqtijxildoonbwnpv7dyd6ef3qdgads2jc4su'
Parameters:

base (None, str or Multibase, optional) – the multibase to be used for encoding

Raises:

KeyError – see multiformats.multibase.Multibase.encode

Return type:

str

property hashfun

Multihash used to produce the multihash digest.

Example usage:

>>> s = "zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA"
>>> cid = CID.decode(s)
>>> cid.hashfun
Multicodec(name='sha2-256', tag='multihash', code='0x12',
           status='permanent', description='')
Return type:

Multihash

property human_readable

Human-readable representation of the CID.

Example usage:

>>> s = "zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA"
>>> cid = CID.decode(s)
>>> cid.human_readable
'base58btc - cidv1 - raw - (sha2-256 : 256 : 6E6FF7950A36187A801613426E858DCE686CD7D7E3C0FC42EE0330072D245C95)'
Return type:

str

static peer_id(pk_bytes)[source]

Wraps the raw hash of a public key into a PeerID, as a CIDv1.

The pk_bytes argument should be the binary public key, encoded according to the PeerID spec. This can be passed as a bytestring or as a hex string (which will be converted to bytes using bytes.fromhex). Note: the hex string is not multibase encoded.

Example usage with Ed25519 public key:

>>> pk_bytes = bytes.fromhex(
... "1498b5467a63dffa2dc9d9e069caf075d16fc33fdd4c3b01bfadae6433767d93")
... # a 32-byte Ed25519 public key
>>> peer_id = CID.peer_id(pk_bytes)
>>> peer_id
CID('base32', 1, 'libp2p-key',
'00201498b5467a63dffa2dc9d9e069caf075d16fc33fdd4c3b01bfadae6433767d93')
#^^   0x00 = 'identity' multihash used (public key length <= 42)
#  ^^ 0x20 = 32-bytes of raw hash digestlength
>>> str(peer_id)
'bafzaaiautc2um6td375c3soz4bu4v4dv2fx4gp65jq5qdp5nvzsdg5t5sm'

Snippet showing how to obtain the Ed25519 public key bytestring using the cryptography library:

>>> from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
>>> from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
>>> private_key = Ed25519PrivateKey.generate()
>>> public_key = private_key.public_key()
>>> pk_bytes = public_key.public_bytes(
...     encoding=Encoding.Raw,
...     format=PublicFormat.Raw
... )
>>> pk_bytes.hex()
"1498b5467a63dffa2dc9d9e069caf075d16fc33fdd4c3b01bfadae6433767d93"

Example usage with DER-encoded RSA public key:

>>> pk_bytes = bytes.fromhex(
... "30820122300d06092a864886f70d01010105000382010f003082010a02820101"
... "009a56a5c11e2705d0bfe0cd1fa66d5e519095cc741b62ed99ddf129c32e046e"
... "5ba3958bb8a068b05a95a6a0623cc3c889b1581793cd84a34cc2307e0dd74c70"
... "b4f230c74e5063ecd8e906d372be4eba13f47d04427a717ac78cb12b4b9c2ab5"
... "591f36f98021a70f84d782c36c51819054228ff35a45efa3f82b27849ec89036"
... "26b4a4c4b40f9f74b79caf55253687124c79cb10cd3bc73f0c44fbd341e5417d"
... "2e85e900d22849d2bc85ca6bf037f1f5b4f9759b4b6942fccdf1140b30ea7557"
... "87deb5c373c5953c14d64b523959a76a32a599903974a98cf38d4aaac7e359f8"
... "6b00a91dcf424bf794592139e7097d7e65889259227c07155770276b6eda4cec"
... "370203010001")
... # a 294-byte RSA public key
>>> peer_id = CID.peer_id(pk_bytes)
>>> peer_id
CID('base32', 1, 'libp2p-key',
'1220c1a6513ffb14f202f75453c49666a5b9d7ed9a1a068891daf824d477573f829f')
#^^   0x12 = 'sha2-256' multihash used (public key length > 42)
#  ^^ 0x20 = 32-bytes of raw hash digest length
>>> str(peer_id)
'bafzbeigbuzit76yu6ibpovctyslgnjnz27wzugqgrci5v6be2r3vop4ct4'

Snippet showing how to obtain the RSA public key bytestring using the cryptography library:

>>> from cryptography.hazmat.primitives.asymmetric import rsa
>>> from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
>>> private_key = rsa.generate_private_key(
...     public_exponent=65537,
...     key_size=2048,
... )
>>> public_key = private_key.public_key()
>>> pk_bytes = public_key.public_bytes(
...     encoding=Encoding.DER,
...     format=PublicFormat.SubjectPublicKeyInfo
... )
>>> pk_bytes.hex()
"30820122300d06092a864886f70d01010105000382010f003082010a02820101"
"009a56a5c11e2705d0bfe0cd1fa66d5e519095cc741b62ed99ddf129c32e046e"
"5ba3958bb8a068b05a95a6a0623cc3c889b1581793cd84a34cc2307e0dd74c70"
"b4f230c74e5063ecd8e906d372be4eba13f47d04427a717ac78cb12b4b9c2ab5"
"591f36f98021a70f84d782c36c51819054228ff35a45efa3f82b27849ec89036"
"26b4a4c4b40f9f74b79caf55253687124c79cb10cd3bc73f0c44fbd341e5417d"
"2e85e900d22849d2bc85ca6bf037f1f5b4f9759b4b6942fccdf1140b30ea7557"
"87deb5c373c5953c14d64b523959a76a32a599903974a98cf38d4aaac7e359f8"
"6b00a91dcf424bf794592139e7097d7e65889259227c07155770276b6eda4cec"
"370203010001"
Parameters:

pk_bytes (str or BytesLike) – the public key bytes

Raises:

ValueError – if pk_bytes is passed as a string and is not the hex-string of some bytes

Return type:

CID

property raw_digest

Raw hash digest, decoded from the multihash digest.

Example usage:

>>> s = "zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA"
>>> cid = CID.decode(s)
>>> cid.raw_digest.hex()
'6e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95'
Return type:

bytes

set(*, base=None, version=None, codec=None)[source]

Returns a new CID obtained by setting new values for one or more of: base, version, or codec.

Example usage:

>>> s = "zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA"
>>> cid = CID.decode(s)
>>> cid
CID('base58btc', 1, 'raw',
'12206e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95')
>>> cid.set(base="base32")
CID('base32', 1, 'raw',
'12206e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95')
>>> cid.set(codec="dag-cbor")
CID('base58btc', 1, 'dag-cbor',
'12206e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95')
>>> cid.set(version=0, codec="dag-pb")
CID('base58btc', 0, 'dag-pb',
'12206e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95')
>>> cid
CID('base58btc', 1, 'raw',
'12206e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95')
# Note: 'CID.set' returns new instances,
#       the original 'cid' instance is unchanged

If setting version to 0, base must be ‘base58btc’ and codec must be ‘dag-pb’.

>>> s = "zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA"
>>> cid = CID.decode(s)
>>> cid
CID('base58btc', 1, 'raw',
'12206e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95')
>>> cid.set(version=0, codec="dag-pb")
CID('base58btc', 0, 'dag-pb',
'12206e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95')
>>> cid.set(version=0)
ValueError: CIDv0 multicodec must be 'dag-pb', found 'raw' instead.
>>> cid.set(version=0, codec="dag-pb", base="base32")
ValueError: CIDv0 multibase must be 'base58btc', found 'base32' instead
Parameters:
  • base (None, str or Multibase, optional) – the new CID multibase, or None if multibase unchanged

  • version (None, 0 or 1, optional) – the new CID version, or None if version unchanged

  • codec (None, str or Multicodec, optional) – the new content multicodec, or None if multicodec unchanged

Raises:

KeyError – if the multibase or multicodec are unknown

Return type:

CID

property version

CID version.

Example usage:

>>> s = "zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA"
>>> cid = CID.decode(s)
>>> cid.version
1
Return type:

cid