Designing a Forensically Sound Evidence Container
How we designed macfor's evidence container format to meet ISO 27037 requirements while remaining practical for real-world investigations.
One of the most critical aspects of forensic collection is ensuring evidence integrity. This post explains the design decisions behind macfor's evidence container format.
Design Requirements
We started with several non-negotiable requirements:
- Tamper evidence: Any modification must be detectable
- Self-documenting: The container must explain what it contains
- Chain of custody: Every action must be logged
- Portable: Standard formats that any tool can read
- Practical: Fast to create and reasonable in size
The Container Structure
macfor produces a ZIP archive with a specific internal structure:
evidence-container.zip
├── manifest.json # What was collected
├── chain-of-custody.json # Action log
├── hashes.json # SHA-256 of every file
├── artifacts/ # Raw collected files
├── records/ # Parsed structured data
└── logs/ # Collection logs
Why ZIP?
ZIP was chosen for several reasons:
- Universal support: Every OS can open ZIP files natively
- Streaming creation: Files can be added without buffering the entire archive
- Per-file compression: Each file can be compressed independently
- Metadata preservation: Timestamps and attributes are stored
Manifest Design
The manifest.json file documents the collection:
{
"collection_id": "550e8400-e29b-41d4-a716-446655440000",
"tool_version": "1.0.0",
"collection_time": "2026-01-28T10:30:00Z",
"source": {
"type": "live",
"hostname": "macbook-pro.local",
"os_version": "14.2.1"
},
"plugins": [
{
"id": "shell.history",
"files_collected": 3,
"records_created": 1250
}
]
}
Hash Verification
Every file added to the container is hashed with SHA-256:
{
"artifacts/shell/bash_history": "sha256:abc123...",
"artifacts/shell/zsh_history": "sha256:def456..."
}
This allows verification that no files have been modified since collection.
Chain of Custody
The chain-of-custody.json file logs every significant action:
{
"entries": [
{
"timestamp": "2026-01-28T10:30:01Z",
"action": "collection_started",
"actor": "macfor 1.0.0"
},
{
"timestamp": "2026-01-28T10:30:02Z",
"action": "file_added",
"target": "artifacts/shell/bash_history",
"actor": "shell.history"
}
]
}
ISO 27037 Alignment
Our format aligns with ISO 27037 (Guidelines for identification, collection, acquisition and preservation of digital evidence):
| Requirement | Implementation | |-------------|----------------| | Reproducibility | Deterministic collection with manifest | | Justifiability | Chain of custody documents all actions | | Auditability | Hash verification proves integrity | | Repeatability | Same input produces same artifacts |
Practical Considerations
Compression Trade-offs
We use ZIP's DEFLATE compression for text files but store binary files uncompressed. This balances size reduction with extraction speed.
Large File Handling
For very large files (like database dumps), we stream directly to the ZIP writer rather than buffering in memory.
Atomic Operations
If collection fails midway, the partial container is automatically removed. You either get a complete, valid container or nothing.
Conclusion
The evidence container format is central to macfor's value proposition. By combining standard formats with forensic best practices, we provide evidence that stands up to scrutiny.
For implementation details, see the technical documentation.