-
-
Notifications
You must be signed in to change notification settings - Fork 1
Adding a New Signature
A practical guide for contributors who want to add a new recoverable file format. This is one of the explicitly welcomed contribution areas — read How It Works first for the weak-magic/strong-magic distinction this guide assumes.
Everything lives in byterescue/recovery/signatures.py. Every entry in the SIGNATURES dict needs
matching logic in carve() — nothing is listed "for show."
Each entry is keyed by format name and describes:
| Field | Meaning |
|---|---|
extensions |
File extensions this format is known by |
header |
The magic bytes that mark a candidate's start |
footer |
The magic bytes that mark its end, or None if the format has no reliable footer |
carver |
Which branch of carve() handles this format |
min_size / max_size
|
Sanity bounds; max_size=None means no cap (only safe when a real footer/length exists) |
reliable |
Whether this format's end offset can be proven, not just estimated |
container_based |
Whether the format has real internal structure to validate against (vs. a flat blob) |
false_positive_risk |
Your honest assessment of how often the header magic alone could appear by coincidence |
notes |
Anything a future reader needs to know about why the carving works the way it does |
-
Short/weak magic (2-4 bytes, or a magic that could plausibly appear inside unrelated binary data)?
Your
carve()branch must do a real structural check and reject outright (return nothing, not a guessed result) when that check fails. Look at thebmp,zip, ormp4branches for the pattern — each one rejects a coincidental-magic false positive rather than reporting a broken result. -
Long/distinctive magic (unlikely to appear by coincidence) with no reliable end marker? Accept
it but cap its size and mark it unverified — see the
cappedbranch used for GZIP/7-Zip/FLAC/GIF/TIFF/ RAR/OLE/MKV. - Has both a distinctive magic and a real footer/length field? That's the best case — verify the real end (see PNG's checksummed IEND, or SQLite's page-size × page-count) rather than searching for a footer string that could itself appear elsewhere.
Add a branch dispatched by your carver value. It receives the format name, the full data buffer, and the
candidate's start index i, and must return either a carved result (with whatever end offset your logic
actually proved or estimated) or nothing, if a weak-magic candidate fails its structural check.
If your format can be checked with a real parser (Pillow, zipfile, sqlite3, wave, decompression, or
similar), add that check here so carved results get a genuine Passed/Partial/Failed/Unknown validation —
see How It Works for why this is kept
separate from carving itself.
- Add a synthetic fixture to
tests/fixtures.py— never a real file, hand-built bytes that exercise the format's actual structure (see the existing JPEG-with-embedded-thumbnail or multi-entry-ZIP fixtures for the level of realism expected). - Add carving-correctness and false-positive-rejection cases to
tests/test_signatures.py— see Testing. - Add your format's row to Recovery Signatures, stating plainly whether its end offset is proven or estimated. Don't round up a heuristic to "verified."
Every row in Recovery Signatures is a claim about how trustworthy a result is.
Overstating a format's reliability is worse than not supporting it — mark it unverified/heuristic if
that's genuinely all the format allows, and say so in notes.
Getting Started
Recovery
Help
Developers