multiformats / multiformats/py-multihash
BLAKE3 only supports fixed 32-byte output — should support variable length up to 128 bytes
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 17
- Forks
- 17
- Avg merge
- 1h 5m
- Merged PRs (30d)
- 3
Description
Blake3Hash always produces a 32-byte digest. Go's BLAKE3 registration supports variable-length output (32, 64, 128 bytes, up to max 128). Calling sum(data, "blake3", length=64) raises TruncationError because the digest is only 32 bytes, even though BLAKE3 natively supports extended output.
Problem
In multihash/funcs.py:
class Blake3Hash:
digest_size: int = 32 # Always 32 bytes
def digest(self) -> bytes:
return self._hasher.digest() # Always returns 32 bytes
The blake3 Python library supports variable-length output:
import blake3
h = blake3.blake3()
h.update(b"foo")
h.digest(64) # Returns 64 bytes ✅
h.digest(128) # Returns 128 bytes ✅
But the wrapper doesn't use this capability. So:
from multihash import sum, Func
# This raises TruncationError:
mh = sum(b"foo", Func.blake3, length=64)
# TruncationError: truncation length 64 exceeds digest size 32
Go's implementation uses RegisterVariableSize:
multihash.RegisterVariableSize(multihash.BLAKE3, func(size int) (hash.Hash, bool) {
if size == -1 { size = 32 }
else if size > 128 || size <= 0 { return nil, false }
h := blake3.New(size, nil)
return h, true
})
Go test vectors include BLAKE3 at 32, 64, and 128 bytes.
Proposed Solution
Modify Blake3Hash to accept a length parameter:
class Blake3Hash:
MAX_SIZE = 128
def __init__(self, length: int = 32):
self._hasher = blake3.blake3()
self._length = length
self.name = "blake3"
self.digest_size = length
self.block_size = 64
def digest(self) -> bytes:
return self._hasher.digest(self._length)
def copy(self):
c = Blake3Hash(self._length)
c._hasher = self._hasher.copy()
return c
Update FuncReg.hash_from_func() to pass length for BLAKE3 (similar to SHAKE):
@classmethod
def hash_from_func(cls, func, length=None):
new = cls._func_hash[func].new
if new is None:
# Handle SHAKE and BLAKE3 with variable length
if func == Func.blake3:
blake3_len = length if length and length > 0 else 32
if blake3_len > Blake3Hash.MAX_SIZE:
return None
return Blake3Hash(blake3_len)
# ... existing SHAKE handling ...
return new()
Add tests matching Go's test vectors for BLAKE3 at 32, 64, and 128 bytes.
Related
- Go implementation: go-multihash
register/blake3/multihash_blake3.go - Go test vectors: BLAKE3 at 32, 64, 128 bytes in
sum_test.go
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in multihash/funcs.py with Blake3Hash and FuncReg.hash_from_func(), then compare the referenced Go registration and test vectors. Support BLAKE3 output lengths of 32, 64, and 128 bytes while preserving the default behavior and rejecting lengths above 128. Add tests covering those three lengths and verify the existing 32-byte case still passes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cryptography
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100