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 abytes
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 tobytes
usingbytes.fromhex
as a
BytesLike
, in which case it is converted tobytes
directlyas a pair
(multihash_codec, raw_digest)
of a multihash and raw hash digest, which are used to produce a multihash digest via thewrap
metho
If
digest
is specified by a pair, themultihash_codec
value can be specified in the following ways:If
digest
is specified by a pair, theraw_digest
value can be specified in the following ways:as a
str
, in which case it is treated as a hex-string and converted tobytes
usingbytes.fromhex
as a
BytesLike
, in which case it is converted tobytes
directly
- Parameters:
base (
str
orMultibase
) – default multibase to use when encoding this CIDversion – the CID version (0 or 1)
codec (
str
,int
orMulticodec
) – the content multicodecdigest – 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:
- 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:
- 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
orBytesLike
) – 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:
- property digest
Multihash digest.
Example usage:
>>> s = "zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA" >>> cid = CID.decode(s) >>> cid.digest.hex() '12206e6ff7950a36187a801613426e858dce686cd7d7e3c0fc42ee0330072d245c95'
- Return type:
- 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'
- 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:
- 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:
- 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 tobytes
usingbytes.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:
- Raises:
ValueError – if
pk_bytes
is passed as a string and is not the hex-string of some bytes- Return type:
- 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:
- set(*, base=None, version=None, codec=None)[source]
Returns a new CID obtained by setting new values for one or more of:
base
,version
, orcodec
.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’ andcodec
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:
- Raises:
KeyError – if the multibase or multicodec are unknown
- Return type: