multihash package

Submodules

multihash.constants module

multihash.exceptions module

Custom exception hierarchy for multihash operations.

exception multihash.exceptions.HashComputationError[source]

Bases: MultihashError

Raised when hash computation fails.

exception multihash.exceptions.InvalidMultihashError[source]

Bases: MultihashError

Raised when multihash is invalid.

exception multihash.exceptions.MultihashError[source]

Bases: Exception

Base exception for multihash errors.

exception multihash.exceptions.TruncationError[source]

Bases: MultihashError

Raised when truncation length is invalid.

exception multihash.exceptions.UnsupportedCodeError[source]

Bases: MultihashError

Raised when hash code is not supported.

multihash.funcs module

Enumeration of standard multihash functions, and function registry.

This module provides: - Func: IntEnum of supported hash functions - FuncReg: Registry for managing hash function implementations - IdentityHash: hashlib-compatible identity hash - ShakeHash: Wrapper for variable-length SHAKE hashes

The FuncReg class maintains a registry of hash functions that can be: - Retrieved by code, name, or hashlib object - Extended with custom app-specific functions (codes 0x01-0x0F) - Used to create hashlib-compatible hash objects

Standard functions are pre-registered. App-specific functions can be registered/unregistered at runtime.

class multihash.funcs.Blake3Hash[source]

Bases: object

hashlib-compatible wrapper for Blake3 using official blake3 library.

BLAKE3 is a cryptographic hash function that is much faster than MD5, SHA-1, SHA-2, and SHA-3, yet is just as secure as the latest standard SHA-3.

Example:
>>> from multihash import digest
>>> mh = digest(b"hello world", "blake3")
>>> mh.digest.hex()  
'...'
>>> # Or use the hash class directly:
>>> h = Blake3Hash()
>>> h.update(b"hello ")
>>> h.update(b"world")
>>> h.hexdigest()  
'...'
block_size: int = 64
copy() Blake3Hash[source]

Create a copy of the hash state.

digest() bytes[source]

Return digest.

digest_size: int = 32
hexdigest() str[source]

Return hex digest.

name: str = 'blake3'
update(data: bytes) None[source]

Update the hash with data.

class multihash.funcs.DoubleSHA256Hash[source]

Bases: object

hashlib-compatible wrapper for double SHA2-256 (used in Bitcoin).

Applies SHA-256 twice: SHA-256(SHA-256(data)). This is commonly used in Bitcoin and other cryptocurrencies for additional security.

Example:
>>> from multihash import digest
>>> mh = digest(b"hello world", "dbl-sha2-256")
>>> mh.digest.hex()  
'...'
>>> # Or use the hash class directly:
>>> h = DoubleSHA256Hash()
>>> h.update(b"data")
>>> h.hexdigest()  
'...'
block_size: int = 64
copy() DoubleSHA256Hash[source]

Create a copy of the hash state.

digest() bytes[source]

Return digest (double SHA-256).

digest_size: int = 32
hexdigest() str[source]

Return hex digest.

name: str = 'dbl-sha2-256'
update(data: bytes) None[source]

Update the hash with data.

class multihash.funcs.Func(value)[source]

Bases: IntEnum

An enumeration of hash functions supported by multihash.

The name of each member has its hyphens replaced by underscores. The value of each member corresponds to its integer code.

>>> Func.sha2_512.value == 0x13
True
blake2b_104 = 45581
blake2b_112 = 45582
blake2b_120 = 45583
blake2b_128 = 45584
blake2b_136 = 45585
blake2b_144 = 45586
blake2b_152 = 45587
blake2b_16 = 45570
blake2b_160 = 45588
blake2b_168 = 45589
blake2b_176 = 45590
blake2b_184 = 45591
blake2b_192 = 45592
blake2b_200 = 45593
blake2b_208 = 45594
blake2b_216 = 45595
blake2b_224 = 45596
blake2b_232 = 45597
blake2b_24 = 45571
blake2b_240 = 45598
blake2b_248 = 45599
blake2b_256 = 45600
blake2b_264 = 45601
blake2b_272 = 45602
blake2b_280 = 45603
blake2b_288 = 45604
blake2b_296 = 45605
blake2b_304 = 45606
blake2b_312 = 45607
blake2b_32 = 45572
blake2b_320 = 45608
blake2b_328 = 45609
blake2b_336 = 45610
blake2b_344 = 45611
blake2b_352 = 45612
blake2b_360 = 45613
blake2b_368 = 45614
blake2b_376 = 45615
blake2b_384 = 45616
blake2b_392 = 45617
blake2b_40 = 45573
blake2b_400 = 45618
blake2b_408 = 45619
blake2b_416 = 45620
blake2b_424 = 45621
blake2b_432 = 45622
blake2b_440 = 45623
blake2b_448 = 45624
blake2b_456 = 45625
blake2b_464 = 45626
blake2b_472 = 45627
blake2b_48 = 45574
blake2b_480 = 45628
blake2b_488 = 45629
blake2b_496 = 45630
blake2b_504 = 45631
blake2b_512 = 45632
blake2b_56 = 45575
blake2b_64 = 45576
blake2b_72 = 45577
blake2b_8 = 45569
blake2b_80 = 45578
blake2b_88 = 45579
blake2b_96 = 45580
blake2s_104 = 45645
blake2s_112 = 45646
blake2s_120 = 45647
blake2s_128 = 45648
blake2s_136 = 45649
blake2s_144 = 45650
blake2s_152 = 45651
blake2s_16 = 45634
blake2s_160 = 45652
blake2s_168 = 45653
blake2s_176 = 45654
blake2s_184 = 45655
blake2s_192 = 45656
blake2s_200 = 45657
blake2s_208 = 45658
blake2s_216 = 45659
blake2s_224 = 45660
blake2s_232 = 45661
blake2s_24 = 45635
blake2s_240 = 45662
blake2s_248 = 45663
blake2s_256 = 45664
blake2s_32 = 45636
blake2s_40 = 45637
blake2s_48 = 45638
blake2s_56 = 45639
blake2s_64 = 45640
blake2s_72 = 45641
blake2s_8 = 45633
blake2s_80 = 45642
blake2s_88 = 45643
blake2s_96 = 45644
blake3 = 30
dbl_sha2_256 = 86
identity = 0
keccak_224 = 26
keccak_256 = 27
keccak_384 = 28
keccak_512 = 29
md4 = 212
md5 = 213
murmur3_128 = 34
murmur3_32 = 35
ripemd_128 = 4178
ripemd_160 = 4179
ripemd_256 = 4180
ripemd_320 = 4181
sha1 = 17
sha2_224 = 4115
sha2_256 = 18
sha2_256_trunc254_padded = 4114
sha2_384 = 32
sha2_512 = 19
sha2_512_224 = 4116
sha2_512_256 = 4117
sha3_224 = 23
sha3_256 = 22
sha3_384 = 21
sha3_512 = 20
shake_128 = 24
shake_256 = 25
class multihash.funcs.FuncReg[source]

Bases: object

Registry of supported hash functions.

The FuncReg class maintains a registry of hash functions that can be: - Retrieved by code, name, or hashlib object - Extended with custom app-specific functions (codes 0x01-0x0F) - Used to create hashlib-compatible hash objects

Standard functions are pre-registered. App-specific functions can be registered/unregistered at runtime.

Example:

Register an app-specific hash function: >>> FuncReg.register(0x05, “my-custom-hash”, “myhash”, lambda: MyHash()) >>> func = FuncReg.get(“my-custom-hash”) >>> hash_obj = FuncReg.hash_from_func(func)

Unregister an app-specific function: >>> FuncReg.unregister(0x05)

classmethod func_from_hash(hash_obj) Func | int[source]

Return the multihash Func for a hashlib-compatible hash object.

Args:

hash_obj: Hashlib-compatible hash object

Returns:

Func enum or int code

Raises:

KeyError: If hash object name is not registered

classmethod get(func_hint: Func | str | int) Func | int[source]

Return a registered hash function matching the given hint.

classmethod hash_from_func(func: Func | int, length: int | None = None)[source]

Return a hashlib-compatible object for the multihash func.

Args:

func: Hash function code or Func enum length: Optional length for SHAKE hashes. Required for SHAKE. Returns None if None for SHAKE.

Returns:

Hash object or None if not available

Note:

SHAKE functions (shake_128, shake_256) require a length parameter to specify the output digest size. If length is None for SHAKE functions, this method returns None.

classmethod register(code: int, name: str, hash_name: str | None = None, hash_new=None) None[source]

Add a function to the registry.

For standard functions already registered, this updates the hash_new if provided. For app-specific functions (0x01-0x0f), replaces existing.

classmethod reset() None[source]

Reset the registry to the standard multihash functions.

classmethod unregister(code: int) None[source]

Remove an application-specific function from the registry.

class multihash.funcs.IdentityHash[source]

Bases: object

hashlib-compatible algorithm where the input is the digest.

property block_size: int
copy() IdentityHash[source]
digest() bytes[source]
property digest_size: int
hexdigest() str[source]
name: str = 'identity'
update(data: bytes) None[source]
class multihash.funcs.Murmur3_128Hash(seed: int = 0)[source]

Bases: object

hashlib-compatible wrapper for MurmurHash3 128-bit using official mmh3 library.

MurmurHash3 is a fast, non-cryptographic hash function suitable for hash-based lookups. Note: Not suitable for cryptographic purposes.

Example:
>>> from multihash import digest
>>> mh = digest(b"hello world", "murmur3-128")
>>> mh.digest.hex()  
'...'
>>> # Or use the hash class directly with a custom seed:
>>> h = Murmur3_128Hash(seed=42)
>>> h.update(b"data")
>>> h.hexdigest()  
'...'
block_size: int = 1
copy() Murmur3_128Hash[source]

Create a copy of the hash state.

digest() bytes[source]

Return 128-bit digest.

digest_size: int = 16
hexdigest() str[source]

Return hex digest.

name: str = 'murmur3-128'
update(data: bytes) None[source]

Update the hash with data.

class multihash.funcs.Murmur3_32Hash(seed: int = 0)[source]

Bases: object

hashlib-compatible wrapper for MurmurHash3 32-bit using official mmh3 library.

MurmurHash3 32-bit variant is a fast, non-cryptographic hash function. Note: Not suitable for cryptographic purposes.

Example:
>>> from multihash import digest
>>> mh = digest(b"hello world", "murmur3-32")
>>> mh.digest.hex()  
'...'
>>> # Or use the hash class directly with a custom seed:
>>> h = Murmur3_32Hash(seed=0)
>>> h.update(b"data")
>>> h.hexdigest()  
'...'
block_size: int = 1
copy() Murmur3_32Hash[source]

Create a copy of the hash state.

digest() bytes[source]

Return 32-bit digest.

digest_size: int = 4
hexdigest() str[source]

Return hex digest.

name: str = 'murmur3-32'
update(data: bytes) None[source]

Update the hash with data.

class multihash.funcs.SHA2_256_Trunc254_Padded_Hash[source]

Bases: object

hashlib-compatible wrapper for SHA2-256 truncated to 254 bits and padded.

block_size: int = 64
copy() SHA2_256_Trunc254_Padded_Hash[source]

Create a copy of the hash state.

digest() bytes[source]

Return digest (SHA-256 truncated to 254 bits = 31 bytes).

digest_size: int = 31
hexdigest() str[source]

Return hex digest.

name: str = 'sha2-256-trunc254-padded'
update(data: bytes) None[source]

Update the hash with data.

class multihash.funcs.ShakeHash(shake_func, length: int)[source]

Bases: object

Wrapper for SHAKE variable-length hash functions.

copy() ShakeHash[source]

Create a copy of the hash state.

digest() bytes[source]

Return digest of specified length.

hexdigest() str[source]

Return hex digest.

update(data: bytes) None[source]

Update the hash with data.

multihash.multihash module

class multihash.multihash.Multihash(code=None, name=None, length=None, digest=None, func=None)[source]

Bases: Multihash

A named tuple representing a multihash function and digest.

This extends the base namedtuple with additional methods for encoding, verification, and compatibility with both py-multihash and pymultihash APIs.

encode(encoding=None)[source]

Encode into a multihash-encoded digest.

Args:

encoding: Optional encoding name (e.g., ‘base64’, ‘hex’, ‘base58’)

Returns:

bytes: The encoded multihash

property func

Return the hash function as a Func enum if possible, otherwise the code.

classmethod read(stream: BinaryIO) Multihash[source]

Read a multihash from a binary stream.

This method reads a varint-encoded multihash from a stream, similar to the Rust implementation’s Multihash::read() method. It reads the code and length as varints, then reads the digest bytes.

Args:

stream: A binary stream object with read() method (e.g., file handle, BytesIO)

Returns:

Multihash: A new Multihash instance read from the stream

Raises:

ValueError: If the stream data is invalid or insufficient TypeError: If stream is not a valid binary stream

Example:

Reading from a BytesIO stream: >>> from io import BytesIO >>> data = BytesIO(b’x12x20’ + b’0’ * 32) # sha2-256 with 32-byte digest >>> mh = Multihash.read(data)

Reading from a file: >>> with open(“multihash.bin”, “rb”) as f: … mh = Multihash.read(f)

Reading multiple multihashes from a stream: >>> from io import BytesIO >>> data = BytesIO(b’x12x20’ + b’0’ * 32 + b’x12x20’ + b’1’ * 32) >>> mh1 = Multihash.read(data) >>> mh2 = Multihash.read(data)

to_json(verbose: bool = False) str[source]

Convert Multihash to JSON string.

Args:

verbose: If True, include ‘name’ field in output

Returns:

JSON string representation

Raises:

ValueError: If base64 encoding or JSON serialization fails

Example:
>>> mh = sum(b"example", Func.sha2_256)
>>> mh.to_json()  
'{"code": 18, "length": 32, "digest": "..."}'
>>> mh.to_json(verbose=True)  
'{"code": 18, "length": 32, "digest": "...", "name": "sha2-256"}'
verify(data)[source]

Does the given data hash to the digest in this multihash?

This method uses self.length (which may be truncated) for verification to ensure it matches the original multihash exactly. For truncated multihashes, verification uses the truncated length, not the full digest length.

Args:

data: The data to verify

Returns:

bool: True if the data matches the digest

Example:
>>> mh = sum(b"hello", Func.sha2_256, length=16)  # Truncated to 16 bytes
>>> mh.verify(b"hello")  # Verifies against 16-byte truncated digest
True
write(stream: BinaryIO) int[source]

Write this multihash to a binary stream.

This method writes the multihash to a stream in varint-encoded format, similar to the Rust implementation’s Multihash::write() method.

Args:

stream: A binary stream object with write() method (e.g., file handle, BytesIO)

Returns:

int: The number of bytes written to the stream

Raises:

TypeError: If stream is not a valid binary stream OSError: If writing to the stream fails

Example:

Writing to a BytesIO stream: >>> from io import BytesIO >>> mh = sum(b”hello”, Func.sha2_256) >>> stream = BytesIO() >>> bytes_written = mh.write(stream) >>> stream.getvalue() # Get the written bytes

Writing to a file: >>> mh = sum(b”hello”, Func.sha2_256) >>> with open(“multihash.bin”, “wb”) as f: … bytes_written = mh.write(f)

Writing multiple multihashes to a stream: >>> from io import BytesIO >>> mh1 = sum(b”data1”, Func.sha2_256) >>> mh2 = sum(b”data2”, Func.sha2_256) >>> stream = BytesIO() >>> mh1.write(stream) >>> mh2.write(stream)

class multihash.multihash.MultihashSet(iterable=None)[source]

Bases: object

A specialized collection for managing unique Multihash values.

This class provides both Go-compatible API (Add, Remove, Has, All) and Pythonic set operations. It ensures type safety by only accepting Multihash objects.

Example:
>>> mh_set = MultihashSet()
>>> mh1 = sum(b"file1", Func.sha2_256)
>>> mh_set.Add(mh1)  # Go-style
>>> mh2 = sum(b"file2", Func.sha2_256)  # Define mh2
>>> mh_set.add(mh2)   # Python-style
>>> mh_set.Has(mh1)   # True
True
>>> len(mh_set)       # 2
2
Add(mh: Multihash) None[source]

Add a Multihash to the set (Go-style API).

Args:

mh: Multihash object to add

Raises:

TypeError: If mh is not a Multihash object

All() list[Multihash][source]

Return all Multihash objects in the set (Go-style API).

Returns:

List of all Multihash objects in the set

Has(mh: Multihash) bool[source]

Check if a Multihash is in the set (Go-style API).

Args:

mh: Multihash object to check

Returns:

True if mh is in the set, False otherwise

Remove(mh: Multihash) None[source]

Remove a Multihash from the set (Go-style API).

Args:

mh: Multihash object to remove

Raises:

KeyError: If mh is not in the set TypeError: If mh is not a Multihash object

add(mh: Multihash) None[source]

Add a Multihash to the set (Python-style API).

Args:

mh: Multihash object to add

Raises:

TypeError: If mh is not a Multihash object

clear() None[source]

Remove all Multihash objects from the set.

difference(other: MultihashSet) MultihashSet[source]

Return a new MultihashSet with elements in this set but not in other.

Args:

other: Another MultihashSet to difference with

Returns:

New MultihashSet containing elements only in this set

discard(mh: Multihash) None[source]

Remove a Multihash from the set if present (does not raise KeyError).

Args:

mh: Multihash object to remove

intersection(other: MultihashSet) MultihashSet[source]

Return a new MultihashSet with elements common to both sets.

Args:

other: Another MultihashSet to intersect with

Returns:

New MultihashSet containing common elements

remove(mh: Multihash) None[source]

Remove a Multihash from the set (Python-style API).

Args:

mh: Multihash object to remove

Raises:

KeyError: If mh is not in the set TypeError: If mh is not a Multihash object

symmetric_difference(other: MultihashSet) MultihashSet[source]

Return a new MultihashSet with elements in either set but not both.

Args:

other: Another MultihashSet to symmetric difference with

Returns:

New MultihashSet containing elements in either set but not both

union(other: MultihashSet) MultihashSet[source]

Return a new MultihashSet with elements from both sets.

Args:

other: Another MultihashSet to union with

Returns:

New MultihashSet containing elements from both sets

multihash.multihash.coerce_code(hash_fn)[source]

Converts a hash function name into its code

If passed a number it will return the number if it’s a valid code

Parameters:

hash_fn – The input hash function can be - str, the name of the hash function - int, the code of the hash function

Returns:

hash function code

Return type:

int

Raises:
  • ValueError – if the hash function is not supported

  • ValueError – if the hash code is not supported

  • ValueError – if the hash type is not a string or an int

multihash.multihash.decode(multihash)[source]

Decode a hash from the given multihash

Parameters:

multihash (bytes) – multihash

Returns:

decoded multihash.Multihash object

Return type:

multihash.Multihash

Raises:
  • TypeError – if multihash is not of type bytes

  • ValueError – if the length of multihash is less than 3 characters

  • ValueError – if the code is invalid

  • ValueError – if the length is invalid

  • ValueError – if the length is not same as the digest

multihash.multihash.digest(data, func, length: int | None = None)[source]

Hash the given data into a new Multihash.

The given hash function func is used to perform the hashing. It must be a registered hash function (see FuncReg).

Args:

data: The data to hash (bytes) func: The hash function to use (Func enum, str, or int) length: Optional truncation length (-1 for full digest, None for auto)

Returns:

Multihash: A new Multihash instance with the computed digest

Example:
>>> data = b'foo'
>>> mh = digest(data, Func.sha1)
>>> mh.encode('base64')
b'ERQL7se16j8P28ldDdR/PFvCddqKMw=='
>>> mh_truncated = digest(data, Func.sha2_256, length=16)
multihash.multihash.encode(digest, code, length=None)[source]

Encode a hash digest along with the specified function code

Parameters:
  • digest (bytes) – hash digest

  • code ((int or str)) – hash function code

  • length (int) – hash digest length

Returns:

encoded multihash

Return type:

bytes

Raises:
  • TypeError – when the digest is not a bytes object

  • ValueError – when the digest length is not correct

multihash.multihash.from_b58_string(multihash)[source]

Convert the given base58 encoded string to a multihash

Parameters:

multihash (str) – base58 encoded multihash string

Returns:

decoded multihash

Return type:

bytes

Raises:

TypeError, if the multihash has incorrect type

multihash.multihash.from_hex_string(multihash)[source]

Convert the given hex encoded string to a multihash

Parameters:

multihash (str) – hex multihash encoded string

Returns:

input multihash in bytes

Return type:

bytes

Raises:

TypeError, if the multihash has incorrect type

multihash.multihash.from_json(json_str: str) Multihash[source]

Create Multihash from JSON string.

Args:

json_str: JSON string representation of Multihash

Returns:

Multihash instance

Raises:

ValueError: If JSON is invalid or missing required fields TypeError: If digest cannot be decoded

Example:
>>> mh_test = sum(b"test", Func.sha2_256)
>>> json_str = mh_test.to_json()
>>> mh = from_json(json_str)
>>> mh_test2 = sum(b"test", Func.sha2_256)
>>> json_str_verbose = mh_test2.to_json(verbose=True)
>>> mh = from_json(json_str_verbose)
multihash.multihash.get_prefix(multihash)[source]

Return the prefix from the multihash

Parameters:

multihash (bytes) – input multihash

Returns:

multihash prefix

Return type:

bytes

Raises:

ValueError – when the multihash is invalid

multihash.multihash.is_app_code(code)[source]

Checks whether a code is part of the app range

Parameters:

code (int) – input code

Returns:

if code is in the app range or not

Return type:

bool

multihash.multihash.is_valid(multihash)[source]

Check if the given buffer is a valid multihash

Parameters:

multihash (bytes) – input multihash

Returns:

if the input is a valid multihash or not

Return type:

bool

multihash.multihash.is_valid_code(code)[source]

Checks whether a multihash code is valid or not

Parameters:

code (int) – input code

Returns:

if the code valid or not

Return type:

bool

multihash.multihash.sum(data: bytes, code: Func | str | int, length: int | None = None) Multihash[source]

Compute multihash for data (Go-compatible API).

This function provides a Go-compatible API for computing multihashes. It is a thin wrapper around digest() that follows Go’s multihash.Sum() convention where length=-1 means full digest.

Use this function when: - Migrating from Go multihash implementations - You prefer the Go-style API naming

Use digest() when: - You prefer Pythonic naming conventions - You want the more descriptive function name

Args:

data: Input data to hash (bytes) code: Hash function code/name (Func enum, str, or int) length: Truncation length (-1 for full digest, None for auto, or specific length)

Returns:

Multihash: A new Multihash instance with the computed digest

Example:
>>> mh = sum(b"hello", "sha2-256")
>>> mh_truncated = sum(b"hello", "sha2-256", length=16)
>>> mh_full = sum(b"hello", "sha2-256", length=-1)  # Full digest
multihash.multihash.sum_stream(stream: BinaryIO, code: Func | str | int, length: int | None = None, chunk_size: int = 8192) Multihash[source]

Compute multihash from a stream/file-like object.

This function reads data from a file-like object in chunks and computes the multihash incrementally for memory efficiency.

Args:

stream: File-like object with read() method (e.g., file handle, BytesIO) code: Hash function code/name (Func enum, str, or int) length: Optional truncation length (-1 for full digest, None for auto) chunk_size: Size of chunks to read from stream (default: 8192 bytes)

Returns:

Multihash: A new Multihash instance with the computed digest

Raises:

HashComputationError: If hash computation fails TruncationError: If truncation length is invalid ValueError: If chunk_size is not positive

Example:

Using with a file handle: >>> with open(“large_file.bin”, “rb”) as f: … mh = sum_stream(f, “sha2-256”)

Using with BytesIO: >>> from io import BytesIO >>> data = BytesIO(b”streaming data”) >>> mh = sum_stream(data, Func.sha2_256)

Using with truncation: >>> with open(“file.bin”, “rb”) as f: … mh = sum_stream(f, Func.sha2_256, length=16)

Using with custom chunk size: >>> with open(“large_file.bin”, “rb”) as f: … mh = sum_stream(f, Func.sha2_256, chunk_size=16384)

multihash.multihash.to_b58_string(multihash)[source]

Convert the given multihash to a base58 encoded string

Parameters:

multihash (bytes) – multihash to base58 encode

Returns:

base58 encoded multihash string

Return type:

str

Raises:

TypeError, if the multihash has incorrect type

multihash.multihash.to_hex_string(multihash)[source]

Convert the given multihash to a hex encoded string

Parameters:

hash (bytes) – the multihash to be converted to hex string

Returns:

input multihash in str

Return type:

str

Raises:

TypeError, if the multihash has incorrect type

Module contents

Top-level package for py-multihash.

class multihash.Func(value)[source]

Bases: IntEnum

An enumeration of hash functions supported by multihash.

The name of each member has its hyphens replaced by underscores. The value of each member corresponds to its integer code.

>>> Func.sha2_512.value == 0x13
True
blake2b_104 = 45581
blake2b_112 = 45582
blake2b_120 = 45583
blake2b_128 = 45584
blake2b_136 = 45585
blake2b_144 = 45586
blake2b_152 = 45587
blake2b_16 = 45570
blake2b_160 = 45588
blake2b_168 = 45589
blake2b_176 = 45590
blake2b_184 = 45591
blake2b_192 = 45592
blake2b_200 = 45593
blake2b_208 = 45594
blake2b_216 = 45595
blake2b_224 = 45596
blake2b_232 = 45597
blake2b_24 = 45571
blake2b_240 = 45598
blake2b_248 = 45599
blake2b_256 = 45600
blake2b_264 = 45601
blake2b_272 = 45602
blake2b_280 = 45603
blake2b_288 = 45604
blake2b_296 = 45605
blake2b_304 = 45606
blake2b_312 = 45607
blake2b_32 = 45572
blake2b_320 = 45608
blake2b_328 = 45609
blake2b_336 = 45610
blake2b_344 = 45611
blake2b_352 = 45612
blake2b_360 = 45613
blake2b_368 = 45614
blake2b_376 = 45615
blake2b_384 = 45616
blake2b_392 = 45617
blake2b_40 = 45573
blake2b_400 = 45618
blake2b_408 = 45619
blake2b_416 = 45620
blake2b_424 = 45621
blake2b_432 = 45622
blake2b_440 = 45623
blake2b_448 = 45624
blake2b_456 = 45625
blake2b_464 = 45626
blake2b_472 = 45627
blake2b_48 = 45574
blake2b_480 = 45628
blake2b_488 = 45629
blake2b_496 = 45630
blake2b_504 = 45631
blake2b_512 = 45632
blake2b_56 = 45575
blake2b_64 = 45576
blake2b_72 = 45577
blake2b_8 = 45569
blake2b_80 = 45578
blake2b_88 = 45579
blake2b_96 = 45580
blake2s_104 = 45645
blake2s_112 = 45646
blake2s_120 = 45647
blake2s_128 = 45648
blake2s_136 = 45649
blake2s_144 = 45650
blake2s_152 = 45651
blake2s_16 = 45634
blake2s_160 = 45652
blake2s_168 = 45653
blake2s_176 = 45654
blake2s_184 = 45655
blake2s_192 = 45656
blake2s_200 = 45657
blake2s_208 = 45658
blake2s_216 = 45659
blake2s_224 = 45660
blake2s_232 = 45661
blake2s_24 = 45635
blake2s_240 = 45662
blake2s_248 = 45663
blake2s_256 = 45664
blake2s_32 = 45636
blake2s_40 = 45637
blake2s_48 = 45638
blake2s_56 = 45639
blake2s_64 = 45640
blake2s_72 = 45641
blake2s_8 = 45633
blake2s_80 = 45642
blake2s_88 = 45643
blake2s_96 = 45644
blake3 = 30
dbl_sha2_256 = 86
identity = 0
keccak_224 = 26
keccak_256 = 27
keccak_384 = 28
keccak_512 = 29
md4 = 212
md5 = 213
murmur3_128 = 34
murmur3_32 = 35
ripemd_128 = 4178
ripemd_160 = 4179
ripemd_256 = 4180
ripemd_320 = 4181
sha1 = 17
sha2_224 = 4115
sha2_256 = 18
sha2_256_trunc254_padded = 4114
sha2_384 = 32
sha2_512 = 19
sha2_512_224 = 4116
sha2_512_256 = 4117
sha3_224 = 23
sha3_256 = 22
sha3_384 = 21
sha3_512 = 20
shake_128 = 24
shake_256 = 25
class multihash.FuncReg[source]

Bases: object

Registry of supported hash functions.

The FuncReg class maintains a registry of hash functions that can be: - Retrieved by code, name, or hashlib object - Extended with custom app-specific functions (codes 0x01-0x0F) - Used to create hashlib-compatible hash objects

Standard functions are pre-registered. App-specific functions can be registered/unregistered at runtime.

Example:

Register an app-specific hash function: >>> FuncReg.register(0x05, “my-custom-hash”, “myhash”, lambda: MyHash()) >>> func = FuncReg.get(“my-custom-hash”) >>> hash_obj = FuncReg.hash_from_func(func)

Unregister an app-specific function: >>> FuncReg.unregister(0x05)

classmethod func_from_hash(hash_obj) Func | int[source]

Return the multihash Func for a hashlib-compatible hash object.

Args:

hash_obj: Hashlib-compatible hash object

Returns:

Func enum or int code

Raises:

KeyError: If hash object name is not registered

classmethod get(func_hint: Func | str | int) Func | int[source]

Return a registered hash function matching the given hint.

classmethod hash_from_func(func: Func | int, length: int | None = None)[source]

Return a hashlib-compatible object for the multihash func.

Args:

func: Hash function code or Func enum length: Optional length for SHAKE hashes. Required for SHAKE. Returns None if None for SHAKE.

Returns:

Hash object or None if not available

Note:

SHAKE functions (shake_128, shake_256) require a length parameter to specify the output digest size. If length is None for SHAKE functions, this method returns None.

classmethod register(code: int, name: str, hash_name: str | None = None, hash_new=None) None[source]

Add a function to the registry.

For standard functions already registered, this updates the hash_new if provided. For app-specific functions (0x01-0x0f), replaces existing.

classmethod reset() None[source]

Reset the registry to the standard multihash functions.

classmethod unregister(code: int) None[source]

Remove an application-specific function from the registry.

exception multihash.HashComputationError[source]

Bases: MultihashError

Raised when hash computation fails.

class multihash.IdentityHash[source]

Bases: object

hashlib-compatible algorithm where the input is the digest.

property block_size: int
copy() IdentityHash[source]
digest() bytes[source]
property digest_size: int
hexdigest() str[source]
name: str = 'identity'
update(data: bytes) None[source]
exception multihash.InvalidMultihashError[source]

Bases: MultihashError

Raised when multihash is invalid.

class multihash.Multihash(code=None, name=None, length=None, digest=None, func=None)[source]

Bases: Multihash

A named tuple representing a multihash function and digest.

This extends the base namedtuple with additional methods for encoding, verification, and compatibility with both py-multihash and pymultihash APIs.

encode(encoding=None)[source]

Encode into a multihash-encoded digest.

Args:

encoding: Optional encoding name (e.g., ‘base64’, ‘hex’, ‘base58’)

Returns:

bytes: The encoded multihash

property func

Return the hash function as a Func enum if possible, otherwise the code.

classmethod read(stream: BinaryIO) Multihash[source]

Read a multihash from a binary stream.

This method reads a varint-encoded multihash from a stream, similar to the Rust implementation’s Multihash::read() method. It reads the code and length as varints, then reads the digest bytes.

Args:

stream: A binary stream object with read() method (e.g., file handle, BytesIO)

Returns:

Multihash: A new Multihash instance read from the stream

Raises:

ValueError: If the stream data is invalid or insufficient TypeError: If stream is not a valid binary stream

Example:

Reading from a BytesIO stream: >>> from io import BytesIO >>> data = BytesIO(b’x12x20’ + b’0’ * 32) # sha2-256 with 32-byte digest >>> mh = Multihash.read(data)

Reading from a file: >>> with open(“multihash.bin”, “rb”) as f: … mh = Multihash.read(f)

Reading multiple multihashes from a stream: >>> from io import BytesIO >>> data = BytesIO(b’x12x20’ + b’0’ * 32 + b’x12x20’ + b’1’ * 32) >>> mh1 = Multihash.read(data) >>> mh2 = Multihash.read(data)

to_json(verbose: bool = False) str[source]

Convert Multihash to JSON string.

Args:

verbose: If True, include ‘name’ field in output

Returns:

JSON string representation

Raises:

ValueError: If base64 encoding or JSON serialization fails

Example:
>>> mh = sum(b"example", Func.sha2_256)
>>> mh.to_json()  
'{"code": 18, "length": 32, "digest": "..."}'
>>> mh.to_json(verbose=True)  
'{"code": 18, "length": 32, "digest": "...", "name": "sha2-256"}'
verify(data)[source]

Does the given data hash to the digest in this multihash?

This method uses self.length (which may be truncated) for verification to ensure it matches the original multihash exactly. For truncated multihashes, verification uses the truncated length, not the full digest length.

Args:

data: The data to verify

Returns:

bool: True if the data matches the digest

Example:
>>> mh = sum(b"hello", Func.sha2_256, length=16)  # Truncated to 16 bytes
>>> mh.verify(b"hello")  # Verifies against 16-byte truncated digest
True
write(stream: BinaryIO) int[source]

Write this multihash to a binary stream.

This method writes the multihash to a stream in varint-encoded format, similar to the Rust implementation’s Multihash::write() method.

Args:

stream: A binary stream object with write() method (e.g., file handle, BytesIO)

Returns:

int: The number of bytes written to the stream

Raises:

TypeError: If stream is not a valid binary stream OSError: If writing to the stream fails

Example:

Writing to a BytesIO stream: >>> from io import BytesIO >>> mh = sum(b”hello”, Func.sha2_256) >>> stream = BytesIO() >>> bytes_written = mh.write(stream) >>> stream.getvalue() # Get the written bytes

Writing to a file: >>> mh = sum(b”hello”, Func.sha2_256) >>> with open(“multihash.bin”, “wb”) as f: … bytes_written = mh.write(f)

Writing multiple multihashes to a stream: >>> from io import BytesIO >>> mh1 = sum(b”data1”, Func.sha2_256) >>> mh2 = sum(b”data2”, Func.sha2_256) >>> stream = BytesIO() >>> mh1.write(stream) >>> mh2.write(stream)

exception multihash.MultihashError[source]

Bases: Exception

Base exception for multihash errors.

class multihash.MultihashSet(iterable=None)[source]

Bases: object

A specialized collection for managing unique Multihash values.

This class provides both Go-compatible API (Add, Remove, Has, All) and Pythonic set operations. It ensures type safety by only accepting Multihash objects.

Example:
>>> mh_set = MultihashSet()
>>> mh1 = sum(b"file1", Func.sha2_256)
>>> mh_set.Add(mh1)  # Go-style
>>> mh2 = sum(b"file2", Func.sha2_256)  # Define mh2
>>> mh_set.add(mh2)   # Python-style
>>> mh_set.Has(mh1)   # True
True
>>> len(mh_set)       # 2
2
Add(mh: Multihash) None[source]

Add a Multihash to the set (Go-style API).

Args:

mh: Multihash object to add

Raises:

TypeError: If mh is not a Multihash object

All() list[Multihash][source]

Return all Multihash objects in the set (Go-style API).

Returns:

List of all Multihash objects in the set

Has(mh: Multihash) bool[source]

Check if a Multihash is in the set (Go-style API).

Args:

mh: Multihash object to check

Returns:

True if mh is in the set, False otherwise

Remove(mh: Multihash) None[source]

Remove a Multihash from the set (Go-style API).

Args:

mh: Multihash object to remove

Raises:

KeyError: If mh is not in the set TypeError: If mh is not a Multihash object

add(mh: Multihash) None[source]

Add a Multihash to the set (Python-style API).

Args:

mh: Multihash object to add

Raises:

TypeError: If mh is not a Multihash object

clear() None[source]

Remove all Multihash objects from the set.

difference(other: MultihashSet) MultihashSet[source]

Return a new MultihashSet with elements in this set but not in other.

Args:

other: Another MultihashSet to difference with

Returns:

New MultihashSet containing elements only in this set

discard(mh: Multihash) None[source]

Remove a Multihash from the set if present (does not raise KeyError).

Args:

mh: Multihash object to remove

intersection(other: MultihashSet) MultihashSet[source]

Return a new MultihashSet with elements common to both sets.

Args:

other: Another MultihashSet to intersect with

Returns:

New MultihashSet containing common elements

remove(mh: Multihash) None[source]

Remove a Multihash from the set (Python-style API).

Args:

mh: Multihash object to remove

Raises:

KeyError: If mh is not in the set TypeError: If mh is not a Multihash object

symmetric_difference(other: MultihashSet) MultihashSet[source]

Return a new MultihashSet with elements in either set but not both.

Args:

other: Another MultihashSet to symmetric difference with

Returns:

New MultihashSet containing elements in either set but not both

union(other: MultihashSet) MultihashSet[source]

Return a new MultihashSet with elements from both sets.

Args:

other: Another MultihashSet to union with

Returns:

New MultihashSet containing elements from both sets

class multihash.ShakeHash(shake_func, length: int)[source]

Bases: object

Wrapper for SHAKE variable-length hash functions.

copy() ShakeHash[source]

Create a copy of the hash state.

digest() bytes[source]

Return digest of specified length.

hexdigest() str[source]

Return hex digest.

update(data: bytes) None[source]

Update the hash with data.

exception multihash.TruncationError[source]

Bases: MultihashError

Raised when truncation length is invalid.

exception multihash.UnsupportedCodeError[source]

Bases: MultihashError

Raised when hash code is not supported.

multihash.coerce_code(hash_fn)[source]

Converts a hash function name into its code

If passed a number it will return the number if it’s a valid code

Parameters:

hash_fn – The input hash function can be - str, the name of the hash function - int, the code of the hash function

Returns:

hash function code

Return type:

int

Raises:
  • ValueError – if the hash function is not supported

  • ValueError – if the hash code is not supported

  • ValueError – if the hash type is not a string or an int

multihash.decode(multihash)[source]

Decode a hash from the given multihash

Parameters:

multihash (bytes) – multihash

Returns:

decoded multihash.Multihash object

Return type:

multihash.Multihash

Raises:
  • TypeError – if multihash is not of type bytes

  • ValueError – if the length of multihash is less than 3 characters

  • ValueError – if the code is invalid

  • ValueError – if the length is invalid

  • ValueError – if the length is not same as the digest

multihash.digest(data, func, length: int | None = None)[source]

Hash the given data into a new Multihash.

The given hash function func is used to perform the hashing. It must be a registered hash function (see FuncReg).

Args:

data: The data to hash (bytes) func: The hash function to use (Func enum, str, or int) length: Optional truncation length (-1 for full digest, None for auto)

Returns:

Multihash: A new Multihash instance with the computed digest

Example:
>>> data = b'foo'
>>> mh = digest(data, Func.sha1)
>>> mh.encode('base64')
b'ERQL7se16j8P28ldDdR/PFvCddqKMw=='
>>> mh_truncated = digest(data, Func.sha2_256, length=16)
multihash.encode(digest, code, length=None)[source]

Encode a hash digest along with the specified function code

Parameters:
  • digest (bytes) – hash digest

  • code ((int or str)) – hash function code

  • length (int) – hash digest length

Returns:

encoded multihash

Return type:

bytes

Raises:
  • TypeError – when the digest is not a bytes object

  • ValueError – when the digest length is not correct

multihash.from_b58_string(multihash)[source]

Convert the given base58 encoded string to a multihash

Parameters:

multihash (str) – base58 encoded multihash string

Returns:

decoded multihash

Return type:

bytes

Raises:

TypeError, if the multihash has incorrect type

multihash.from_hex_string(multihash)[source]

Convert the given hex encoded string to a multihash

Parameters:

multihash (str) – hex multihash encoded string

Returns:

input multihash in bytes

Return type:

bytes

Raises:

TypeError, if the multihash has incorrect type

multihash.from_json(json_str: str) Multihash[source]

Create Multihash from JSON string.

Args:

json_str: JSON string representation of Multihash

Returns:

Multihash instance

Raises:

ValueError: If JSON is invalid or missing required fields TypeError: If digest cannot be decoded

Example:
>>> mh_test = sum(b"test", Func.sha2_256)
>>> json_str = mh_test.to_json()
>>> mh = from_json(json_str)
>>> mh_test2 = sum(b"test", Func.sha2_256)
>>> json_str_verbose = mh_test2.to_json(verbose=True)
>>> mh = from_json(json_str_verbose)
multihash.get_prefix(multihash)[source]

Return the prefix from the multihash

Parameters:

multihash (bytes) – input multihash

Returns:

multihash prefix

Return type:

bytes

Raises:

ValueError – when the multihash is invalid

multihash.is_app_code(code)[source]

Checks whether a code is part of the app range

Parameters:

code (int) – input code

Returns:

if code is in the app range or not

Return type:

bool

multihash.is_valid(multihash)[source]

Check if the given buffer is a valid multihash

Parameters:

multihash (bytes) – input multihash

Returns:

if the input is a valid multihash or not

Return type:

bool

multihash.is_valid_code(code)[source]

Checks whether a multihash code is valid or not

Parameters:

code (int) – input code

Returns:

if the code valid or not

Return type:

bool

multihash.sum(data: bytes, code: Func | str | int, length: int | None = None) Multihash[source]

Compute multihash for data (Go-compatible API).

This function provides a Go-compatible API for computing multihashes. It is a thin wrapper around digest() that follows Go’s multihash.Sum() convention where length=-1 means full digest.

Use this function when: - Migrating from Go multihash implementations - You prefer the Go-style API naming

Use digest() when: - You prefer Pythonic naming conventions - You want the more descriptive function name

Args:

data: Input data to hash (bytes) code: Hash function code/name (Func enum, str, or int) length: Truncation length (-1 for full digest, None for auto, or specific length)

Returns:

Multihash: A new Multihash instance with the computed digest

Example:
>>> mh = sum(b"hello", "sha2-256")
>>> mh_truncated = sum(b"hello", "sha2-256", length=16)
>>> mh_full = sum(b"hello", "sha2-256", length=-1)  # Full digest
multihash.sum_stream(stream: BinaryIO, code: Func | str | int, length: int | None = None, chunk_size: int = 8192) Multihash[source]

Compute multihash from a stream/file-like object.

This function reads data from a file-like object in chunks and computes the multihash incrementally for memory efficiency.

Args:

stream: File-like object with read() method (e.g., file handle, BytesIO) code: Hash function code/name (Func enum, str, or int) length: Optional truncation length (-1 for full digest, None for auto) chunk_size: Size of chunks to read from stream (default: 8192 bytes)

Returns:

Multihash: A new Multihash instance with the computed digest

Raises:

HashComputationError: If hash computation fails TruncationError: If truncation length is invalid ValueError: If chunk_size is not positive

Example:

Using with a file handle: >>> with open(“large_file.bin”, “rb”) as f: … mh = sum_stream(f, “sha2-256”)

Using with BytesIO: >>> from io import BytesIO >>> data = BytesIO(b”streaming data”) >>> mh = sum_stream(data, Func.sha2_256)

Using with truncation: >>> with open(“file.bin”, “rb”) as f: … mh = sum_stream(f, Func.sha2_256, length=16)

Using with custom chunk size: >>> with open(“large_file.bin”, “rb”) as f: … mh = sum_stream(f, Func.sha2_256, chunk_size=16384)

multihash.to_b58_string(multihash)[source]

Convert the given multihash to a base58 encoded string

Parameters:

multihash (bytes) – multihash to base58 encode

Returns:

base58 encoded multihash string

Return type:

str

Raises:

TypeError, if the multihash has incorrect type

multihash.to_hex_string(multihash)[source]

Convert the given multihash to a hex encoded string

Parameters:

hash (bytes) – the multihash to be converted to hex string

Returns:

input multihash in str

Return type:

str

Raises:

TypeError, if the multihash has incorrect type