get_prefix() returns multihash[:2], assuming the code and length varints are each exactly 1 byte. For hash codes > 127 (e.g., sha2-224 at 0x1013, blake2b-256 at 0xB220), the varint encoding is multi-byte, so [:2] returns incorrect/incomplete data.
Problem
In multihash/multihash.py:
def get_prefix(multihash):
if is_valid(multihash):
return multihash[:2] # ← Always returns first 2 bytes
raise ValueError("invalid multihash")
For codes that fit in a single varint byte (0x00–0x7F), this works. But for codes > 0x7F, the varint encoding uses multiple bytes:
| Hash function |
Code |
Varint bytes |
[:2] returns |
Correct prefix |
| sha2-256 |
0x12 |
b'\x12' (1 byte) |
b'\x12\x20' ✅ |
b'\x12\x20' |
| sha2-224 |
0x1013 |
b'\x93 ' (2 bytes) |
b'\x93 ' ❌ |
b'\x93 \x1c' |
| blake2b-256 |
0xB220 |
b'\xa0\xe4\x02' (3 bytes) |
b'\xa0\xe4' ❌ |
b'\xa0\xe4\x02\x20' |
| ripemd-160 |
0x1053 |
b'\xd3 ' (2 bytes) |
b'\xd3 ' ❌ |
b'\xd3 \x14' |
The "prefix" of a multihash is the varint-encoded code + varint-encoded length. Its size varies depending on the code and digest length.
Proposed Solution
Replace the hardcoded slice with proper varint decoding:
def get_prefix(multihash):
if not isinstance(multihash, bytes):
raise TypeError("multihash should be bytes")
if not is_valid(multihash):
raise ValueError("invalid multihash")
buffer = BytesIO(multihash)
# Read code varint
varint.decode_stream(buffer)
# Read length varint
varint.decode_stream(buffer)
# Everything up to current position is the prefix
return multihash[:buffer.tell()]
Add tests with multi-byte varint codes:
def test_get_prefix_multi_byte_code():
mh = sum(b"test", Func.sha2_224)
prefix = get_prefix(mh.encode())
assert prefix == mh.encode()[:3] # 2-byte code + 1-byte length
Related
- File:
multihash/multihash.py, get_prefix() function
- Affected codes: All codes > 0x7F (sha2-224, sha2-512-224, sha2-512-256, ripemd-, blake2b-, blake2s-, keccak-, skein*, etc.)
get_prefix()returnsmultihash[:2], assuming the code and length varints are each exactly 1 byte. For hash codes > 127 (e.g.,sha2-224at0x1013,blake2b-256at0xB220), the varint encoding is multi-byte, so[:2]returns incorrect/incomplete data.Problem
In
multihash/multihash.py:For codes that fit in a single varint byte (0x00–0x7F), this works. But for codes > 0x7F, the varint encoding uses multiple bytes:
[:2]returnsb'\x12'(1 byte)b'\x12\x20'✅b'\x12\x20'b'\x93 '(2 bytes)b'\x93 '❌b'\x93 \x1c'b'\xa0\xe4\x02'(3 bytes)b'\xa0\xe4'❌b'\xa0\xe4\x02\x20'b'\xd3 '(2 bytes)b'\xd3 '❌b'\xd3 \x14'The "prefix" of a multihash is the varint-encoded code + varint-encoded length. Its size varies depending on the code and digest length.
Proposed Solution
Replace the hardcoded slice with proper varint decoding:
Add tests with multi-byte varint codes:
Related
multihash/multihash.py,get_prefix()function