rehashes
Provides Python hashers with serializable internal state that can be persisted and recovered to continue hashing in another context.
Supported algorithms:
- MD5 (
rehashes.PyMd5) - SHA1 (
rehashes.PySha1) - SHA256 (
rehashes.PySha256) - SHA512 (
rehashes.PySha512) - ssdeep ((
rehashes.PySsdeep, basic fuzzy hash evaluation only)
All hashers share the same minimal interface (update/finalize/serialize/deserialize).
This library is powered by Rust and hash implementations are provided by:
- https://github.com/rustcrypto/hashes
- https://github.com/rustysec/fuzzyhash-rs (embedded into library and modified to be serializable)
Motivation
Unlike hashlib, rehashes hashers support state serialization, allowing you to persist and resume hashing across processes or sessions. Standard hashlib objects cannot be pickled or serialized.
Existing libraries are trying to achieve that by serializing OpenSSL opaque structures, which is very unsafe because the internal structures of OpenSSL are not stable and may vary across versions and platforms. rehashes is a Rust wrapper around rustcrypto/hashes that natively support serialization.
The intended use case of rehashes is to support chunked upload in MWDB Core and Drakvuf Sandbox projects. The idea is to be able to stream uploaded chunks to S3 storage and compute hashes of the whole file without the need to re-read it afterward. This is achieved by serializing the internal state of the hasher and storing it in the shared database (e.g. Redis). Then for each chunk, we can recover the state and update/finalize the hash computation.
As rehashes was made for use in MWDB Core, it supports ssdeep (libfuzzy) computation by embedding the fuzzyhash-rs implementation, that was slightly modified to support serialization.
Installation
pip install rehashes
Pre-built wheels are available for:
- Linux x86_64 and aarch64 (manylinux2014 / glibc 2.17+)
- Python 3.10+ (abi3 stable ABI — one wheel covers all Python versions)
Usage
Basic hashing
from rehashes import PySha256
hasher = PySha256()
hasher.update(b"Hello, ")
hasher.update(b"World!")
print(hasher.finalize())
# "dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f"
All hashers follow the same interface:
from rehashes import PyMd5, PySha1, PySha256, PySha512, PySsdeep
hasher = PySsdeep() # or PySha1(), PySha256(), PySha512(), PySsdeep()
hasher.update(data) # Feed data (bytes) into the hasher
result = hasher.finalize() # Get the hex digest as a string
Serializable state
Warning! Ensure that you're using the same version of library for serializing and deserializing state. Serialized state should be kept server-side and not be exposed e.g. in JWT tokens. Under the hood we use:
- for MD5/SHA-1/SHA-2: https://docs.rs/crypto-common/0.2.1/crypto_common/hazmat/trait.SerializableState.html
- for ssdeep: https://docs.rs/serde_cbor/0.11.2/serde_cbor/
The key feature of rehashes is the ability to serialize and restore the internal hasher state. This enables use cases like chunked file uploads where you need to compute hashes across multiple sessions without re-reading the entire file.
from rehashes import PySha256
# Session 1: Process first chunk of data
hasher = PySha256()
hasher.update(b"chunk 1 data")
# Serialize and persist the state (e.g., to Redis, database, etc.)
state = hasher.serialize()
# Session 2: Recover state and continue hashing
hasher = PySha256.deserialize(state)
hasher.update(b"chunk 2 data")
# Finalize when all data has been processed
print(hasher.finalize())
This works for all supported algorithms including ssdeep:
from rehashes import PySsdeep
hasher = PySsdeep()
hasher.update(b"chunk 1 data")
state = hasher.serialize() # Persist state to shared storage
# ... later, in another process ...
hasher = PySsdeep.deserialize(state)
hasher.update(b"chunk 2 data")
ssdeep_hash = hasher.finalize()
API Reference
Each hasher class (PyMd5, PySha1, PySha256, PySha512, PySsdeep) exposes:
| Method | Description |
|---|---|
__init__() |
Create a new hasher instance |
update(data: bytes) |
Feed data into the hasher |
finalize() -> str |
Return the hash digest as a hex string |
serialize() -> bytes |
Serialize the internal state to bytes |
deserialize(data: bytes) -> Self |
Restore a hasher from serialized state (staticmethod) |
Development
Setup
# Create virtual environment and install maturin
pip install maturin
# Build and install in development mode
maturin develop
# Run tests
pip install pytest
pytest tests/
Building wheels
# Build wheel for current platform
maturin build --release
# Build manylinux wheel
maturin build --release --manylinux manylinux2014 -i python3.10
Metadata
Release files for rehashes 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rehashes-0.3.0.tar.gz | 22.6 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| rehashes-0.3.0-cp310-abi3-musllinux_1_2_x86_64.whl | CPython 3.10 | abi3 | Linux musl 1.2+ x86-64 | Details |
| rehashes-0.3.0-cp310-abi3-musllinux_1_2_aarch64.whl | CPython 3.10 | abi3 | Linux musl 1.2+ ARM64 | Details |
| rehashes-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| rehashes-0.3.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details |
Total release size: 1.9 MB
Release files / rehashes-0.3.0.tar.gz
| Download URL | rehashes-0.3.0.tar.gz |
|---|---|
| Size | 22.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
40ea75f22b79f183c5190ff7bd510d9a283560a25587aa4210dfa2d008aff01c
|
|
BLAKE2b-256 checksum How to use checksums |
309582272af2e29c5f9d6eae5d4d9295ebe1290e8caf37f6a8f8b781fa303d94
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Release files / rehashes-0.3.0-cp310-abi3-musllinux_1_2_x86_64.whl
| Download URL | rehashes-0.3.0-cp310-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 576.7 kB |
| Tags | CPython 3.10 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
dd46cbabebee281ec6ab21f89a42c9f29eeed24c18bddb0490547e24f4eb21d7
|
|
BLAKE2b-256 checksum How to use checksums |
38ce13243cd59be3e27b25c19f8893e56373619cea440736afcb46bd1bfb62b3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Release files / rehashes-0.3.0-cp310-abi3-musllinux_1_2_aarch64.whl
| Download URL | rehashes-0.3.0-cp310-abi3-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 542.1 kB |
| Tags | CPython 3.10 Linux musl 1.2+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
f46177c2b776f6bfb2e039a8e893980a9dfbf2896cd80819220e067d3556e677
|
|
BLAKE2b-256 checksum How to use checksums |
777a63c7dc9a468ac5724a1581465e6d424512bd36b037223ef2843c383d21aa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Release files / rehashes-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rehashes-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 371.0 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
4c864d8537a4a0019c7d789e28cb04ed8af3041286bc7ae48f7006b5cb8c775f
|
|
BLAKE2b-256 checksum How to use checksums |
2185f7ae7f3db032edb3594b28b41ad307c129ea818ebe542cf237897a7311ae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Release files / rehashes-0.3.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rehashes-0.3.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 366.9 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
c6564c6491eac8bb28f8c5c20dd2b9fa3ef80750404b440ecdc6b266dfa37f2e
|
|
BLAKE2b-256 checksum How to use checksums |
6dcfff923c62eab59811d7031b34387883d7e63e2f918e325b563d924ca2a265
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|