multiformats.multihash

Implementation of the multihash spec.

Suggested usage:

>>> from multiformats import multihash

Multihash

class Multihash(codec)[source]

Bases: object

Container class for a multibase encoding.

Example usage:

>>> sha2_256 = multihash.get("sha2-256")
>>> sha2_256
Multihash(codec='sha2-256')
Parameters:

codec (str, int or Multicodec) – the multicodec defining this multihash

property code

Multihash multicodec code.

Example usage:

>>> sha2_256.code
18
# 18 = 0x12
Return type:

int

property codec

The multicodec for this multihash.

Example usage:

>>> sha2_256.codec
Multicodec(name='sha2-256', tag='multihash', code='0x12',
           status='permanent', description='')
Return type:

Multicodec

digest(data, *, size=None)[source]

Computes the raw digest of the given data and wraps it into a multihash digest.

Example usage:

>>> sha2_256 = multihash.get("sha2-256")
>>> data = b"Hello world!"
>>> data.hex()
"48656c6c6f20776f726c6421"
>>> sha2_256.digest(data).hex() # full 32-bytes hash
'1220c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a'
>>> sha2_256.digest(data, size=20).hex() # truncated hash
'1214c0535e4be2b79ffd93291305436bf889314e4a3f'
Parameters:
  • data (BytesLike) – the raw digest

  • size (int or None, optional) – size for the raw digest, in bytes. If not None, raw digest is truncated to fit the given size.

Raises:
  • ValueError – if size parameter is not None and negative.

  • ValueError – if size parameter is not None, max digest size is not None and given size exceeds max digest size.

  • ValueError – if size parameter is None but a size is required for the hash function (e.g. for the KangarooTwelve XOF).

See digest for more information.

Return type:

bytes

property implementation

Returns the implementation of a multihash multicodec, as a pair:

hash_function, max_digest_size = multihash.implementation("sha2-256")

Above, codec is the Multicodec object carrying information about the multihash multicodec, hash_function is the function bytes->bytes computing the raw hashes, and max_digest_size is the max size of the digests produced by hash_function (or None if there is no max size, such as in the case of the 'identity' multihash multicodec).

Example usage:

>>> sha2_256.implementation
(<function _hashlib_sha.<locals>.hashfun at 0x0000029396E22280>, 32)
Return type:

MultihashImpl

property is_cryptographic

Whether this is a cryptographic hash or not, based on whether the codec is tagged as 'multihash' or just 'hash'.

Return type:

bool

property max_digest_size

The maximum size (in bytes) for raw digests of this multihash, or None if there is no maximum size. Used to sense-check the wrapped/unwrapped raw digests.

Example usage:

>>> sha2_256.max_digest_size
32
# 32 bytes = 256 bits
Return type:

Optional[int]

property name

Multihash multicodec name.

Example usage:

>>> sha2_256.name
'sha2-256'
Return type:

str

unwrap(digest)[source]

Unwraps a multihash digest into a hash digest:

<code><size><raw digest> --> <raw digest>

If digest is one or bytes, bytearray or memoryview, the method also checks that the actual hash digest size matches the size listed by the multihash digest.

Example usage:

>>> sha2_256 = multihash.get("sha2-256")
>>> digest = bytes.fromhex(
... "1214c0535e4be2b79ffd93291305436bf889314e4a3f")
>>> sha2_256.unwrap(digest).hex()
'c0535e4be2b79ffd93291305436bf889314e4a3f'
Parameters:

digest (BytesLike or BufferedIOBase) – the multihash digest to be unwrapped

See unwrap for more information.

Return type:

bytes

wrap(raw_digest)[source]

Wraps a raw digest into a multihash digest:

<raw digest> --> <code><size><raw digest>

Example usage:

>>> sha2_256 = multihash.get("sha2-256")
>>> raw_digest = bytes.fromhex(
... "c0535e4be2b79ffd93291305436bf889314e4a3f")
>>> sha2_256.wrap(raw_digest).hex()
"1214c0535e4be2b79ffd93291305436bf889314e4a3f"
Parameters:

raw_digest (BytesLike) – the raw digest

See wrap for more information.

Return type:

bytes

digest

digest(data, hashfun, *, size=None)[source]

Computes the raw digest of the given data and wraps it into a multihash digest.

Example usage:

>>> data = b"Hello world!"
>>> data.hex()
"48656c6c6f20776f726c6421"
>>> multihash.digest(data, "sha2-256").hex() # full 32-bytes hash
'1220c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a'
>>> multihash.digest(data, "sha2-256", size=20).hex()
#         optional truncated hash size ^^^^^^^
'1214c0535e4be2b79ffd93291305436bf889314e4a3f'
#^^   code 0x12 for multihash multicodec "sha2-256"
#  ^^ truncated hash length 0x14 = 20 bytes

Note both multihash code and digest length are wrapped as varints (see the multiformats.varint module) and can span multiple bytes:

>>> multihash.get("skein1024-1024")
Multicodec(name='skein1024-1024', tag='multihash', code='0xb3e0',
           status='draft', description='')
>>> multihash.digest(data, "skein1024-1024").hex()
'e0e702800192e08f5143 ... 3+2+128 = 133 bytes in total
#^^^^^^     3-bytes varint for hash function code 0xb3e0
#      ^^^^ 2-bytes varint for hash digest length 128
>>> from multiformats import varint
>>> hex(varint.decode(bytes.fromhex("e0e702")))
'0xb3e0'
>>> varint.decode(bytes.fromhex("8001"))
128
Parameters:
  • data (BytesLike) – the data to be digested

  • hashfun (str, int or Multihash) – the multihash function name, code or object

  • size (int or None, optional) – size for the raw digest, in bytes. If not None, raw digest is truncated to fit the given size.

Raises:
  • ValueError – if size parameter is not None and negative.

  • ValueError – if size parameter is not None, max digest size is not None and given size exceeds max digest size.

  • ValueError – if size parameter is None but a size is required for the hash function (e.g. for the KangarooTwelve XOF).

Return type:

bytes

exists

exists(name=None, *, code=None)[source]

Checks whether a multihash multicodec with the given name or code exists. This function returns False if a multicodec by given name or code exists, but is not tagged 'multihash'.

Example usage:

>>> multihash.exists("sha1")
True
>>> multihash.exists(code=0x11)
True
>>> from multiformats import multicodec
>>> multicodec.get("cidv1")
Multicodec(name='cidv1', tag='cid', code='0x01',
           status='permanent', description='CIDv1')
>>> multihash.exists("cidv1")
False
Parameters:
  • name (str or None, optional) – the multihash name

  • code (int or None, optional) – the multihash code

Raises:

ValueError – unless exactly one of name and code is specified

Return type:

bool

from_digest

from_digest(digest)[source]

Returns the multihash multicodec for the given digest, according to the code specified by its prefix.

Example usage:

>>> digest = bytes.fromhex("140a9a7a8207a57d03e9c524")
>>> multihash.from_digest(digest)
Multihash(codec='sha3-512')
Parameters:

digest (BytesLike) – the multihash digest

Raises:

KeyError – if no multihash exists with that code

Return type:

Multihash

get

get(name=None, *, code=None)[source]

Gets the multihash multicodec with given name or code.

Example usage:

>>> multihash.get("sha1")
Multihash(codec='sha1')
>>> multihash.get(code=0x11)
Multihash(codec='sha1')
Parameters:
  • name (str or None, optional) – the multihash name

  • code (int or None, optional) – the multihash code

Raises:
  • KeyError – if the multihash does not exist or is not implemented

  • ValueError – unless exactly one of name and code is specified

Return type:

Multihash

is_implemented

is_implemented(name=None, *, code=None)[source]

Checks whether a multihash with the given name or code exists and is implemented.

Example usage:

>>> multihash.is_implemented("sha1")
True
>>> multihash.is_implemented(code=0x11)
True
Parameters:
  • name (str or None, optional) – the multihash name

  • code (int or None, optional) – the multihash code

Raises:

ValueError – unless exactly one of name and code is specified

Return type:

bool

unwrap

unwrap(digest, hashfun=None)[source]

Unwraps a multihash digest into a raw digest:

<code><size><raw digest> --> <raw digest>

If digest is one of bytes, bytearray or memoryview, the method also checks that the actual raw digest size matches the size listed in the multihash digest. If digest is a stream (an instance of BufferedIOBase, specifically), then the number of bytes consumed to produce the raw digest matches the size lised in the multihash digest, and no further bytes are consumed from the stream.

If the optional hashfun is not None, the function additionally enforces that the code from the multihash digest matches the code of the multihash (calls Multihash.unwrap under the hood to do so). Regardless, the function checks that the multihash with code specified by the multihash digest exists and is implemented.

Example usage:

>>> digest = bytes.fromhex(
... "1214c0535e4be2b79ffd93291305436bf889314e4a3f")
>>> multihash.unwrap(digest, "sha2-256").hex()
'c0535e4be2b79ffd93291305436bf889314e4a3f'
Parameters:
Raises:

ValueError – if the unwrapped raw digest exceeds the stated maximum digest size for the multihash function

Return type:

bytes

unwrap_raw

unwrap_raw(digest)[source]

Unwraps a multihash digest into a code and raw digest pair:

<code><size><raw digest> --> (<code>, <raw digest>)

The function checks that the multihash codec with code specified by the multihash digest exists, but does not check whether it is implemented or not.

Example usage:

>>> digest = bytes.fromhex(
... "1214c0535e4be2b79ffd93291305436bf889314e4a3f")
>>> code, digest = multihash.unwrap_raw(digest, "sha2-256")
>>> code
18 # the code 0x12 of 'sha2-256'
>>> digest.hex()
'c0535e4be2b79ffd93291305436bf889314e4a3f'
Parameters:

digest (BytesLike or BufferedIOBase) – the multihash digest

Return type:

Tuple[int, Union[bytes, memoryview]]

wrap

wrap(raw_digest, hashfun)[source]

Wraps a raw digest into a multihash digest using the given multihash:

<raw digest> --> <code><size><raw digest>

If the multihash is passed by name or code, the get function is used to retrieve it.

Example usage:

>>> multihash.get("sha2-256").codec
Multicodec(name='sha2-256', tag='multihash', code='0x12',
           status='permanent', description='')
>>> raw_digest = bytes.fromhex("c0535e4be2b79ffd93291305436bf889314e4a3f")
>>> len(raw_digest)
20
>>> multihash.wrap(raw_digest, "sha2-256").hex()
"1214c0535e4be2b79ffd93291305436bf889314e4a3f"
#^^   code 0x12 for multihash multicodec "sha2-256"
#  ^^ truncated hash length 0x14 = 20 bytes

Note that all digests above are bytes objects, represented here as hex strings for clarity:

>>> hash_digest
b'\xc0S^K\xe2\xb7\x9f\xfd\x93)\x13\x05Ck\xf8\x891NJ?'
>>> multihash.wrap(raw_digest, "sha2-256")
b'\x12\x14\xc0S^K\xe2\xb7\x9f\xfd\x93)\x13\x05Ck\xf8\x891NJ?'
# ^^^^     0x12 -> multihash multicodec "sha2-256"
#     ^^^^ 0x14 -> truncated hash length of 20 bytes
Parameters:
  • raw_digest (BytesLike) – the raw hash digest

  • hashfun (str, int or Multihash) – the multihash function name, code or object

Return type:

bytes