fieldwitness/docs/evidence-guide.md
Aaron D. Lee 490f9d4a1d Rebrand SooSeF to FieldWitness
Complete project rebrand for better positioning in the press freedom
and digital security space. FieldWitness communicates both field
deployment and evidence testimony — appropriate for the target audience
of journalists, NGOs, and human rights organizations.

Rename mapping:
- soosef → fieldwitness (package, CLI, all imports)
- soosef.stegasoo → fieldwitness.stego
- soosef.verisoo → fieldwitness.attest
- ~/.soosef/ → ~/.fwmetadata/ (innocuous data dir name)
- SOOSEF_DATA_DIR → FIELDWITNESS_DATA_DIR
- SoosefConfig → FieldWitnessConfig
- SoosefError → FieldWitnessError

Also includes:
- License switch from MIT to GPL-3.0
- C2PA bridge module (Phase 0-2 MVP): cert.py, export.py, vendor_assertions.py
- README repositioned to lead with provenance/federation, stego backgrounded
- Threat model skeleton at docs/security/threat-model.md
- Planning docs: docs/planning/c2pa-integration.md, docs/planning/gtm-feasibility.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 15:05:13 -04:00

284 lines
9.9 KiB
Markdown

# Evidence Guide
**Audience**: Journalists, investigators, and legal teams who need to create, export, and
verify evidence packages from FieldWitness.
**Prerequisites**: A running FieldWitness instance with at least one attested image or file.
Familiarity with basic CLI commands.
---
## Overview
FieldWitness provides three mechanisms for preserving and sharing evidence outside a running
instance: evidence packages (for handing specific files to third parties), cold archives
(full-state preservation for 10+ year horizons), and selective disclosure (proving specific
records without revealing the rest of the chain). All three include standalone verification
scripts that require no FieldWitness installation.
---
## Evidence Packages
An evidence package is a self-contained ZIP that bundles everything needed for independent
verification of specific attested images or files.
### What is inside an evidence package
| File | Purpose |
|---|---|
| `images/` | Original image files |
| `manifest.json` | Attestation records, chain data, and image hashes |
| `public_key.pem` | Signer's Ed25519 public key |
| `verify.py` | Standalone verification script |
| `README.txt` | Human-readable instructions |
### Creating an evidence package
```bash
# Package specific images with their attestation records
$ fieldwitness evidence export photo1.jpg photo2.jpg --output evidence_package.zip
# Filter by investigation tag
$ fieldwitness evidence export photo1.jpg --investigation "case-2026-001" \
--output evidence_case001.zip
```
### When to create evidence packages
- Before handing evidence to a legal team or court
- When sharing with a partner organization that does not run FieldWitness
- Before crossing a hostile checkpoint (create the package, send it to a trusted party,
then activate the killswitch if needed)
- When an investigation is complete and files must be archived independently
### Verifying an evidence package
The recipient does not need FieldWitness. They need only Python 3.11+ and the `cryptography`
pip package:
```bash
$ python3 -m venv verify-env
$ source verify-env/bin/activate
$ pip install cryptography
$ cd evidence_package/
$ python verify.py
```
The verification script checks:
1. Image SHA-256 hashes match the attestation records in `manifest.json`
2. Chain hash linkage is unbroken (each record's `prev_hash` matches the previous record)
3. Ed25519 signatures are valid (if `public_key.pem` is included)
---
## Cold Archives
A cold archive is a full snapshot of the entire FieldWitness evidence store, designed for
long-term preservation aligned with OAIS (ISO 14721). It is self-describing and includes
everything needed to verify the evidence decades later, even if FieldWitness no longer exists.
### What is inside a cold archive
| File | Purpose |
|---|---|
| `chain/chain.bin` | Raw append-only hash chain binary |
| `chain/state.cbor` | Chain state checkpoint |
| `chain/anchors/` | External timestamp anchor files (RFC 3161 tokens, manual anchors) |
| `attestations/log.bin` | Full attest attestation log |
| `attestations/index/` | LMDB index files |
| `keys/public.pem` | Signer's Ed25519 public key |
| `keys/bundle.enc` | Encrypted key bundle (optional, password-protected) |
| `keys/trusted/` | Trusted collaborator public keys |
| `manifest.json` | Archive metadata and SHA-256 integrity hashes |
| `verify.py` | Standalone verification script |
| `ALGORITHMS.txt` | Cryptographic algorithm documentation |
| `README.txt` | Human-readable description |
### Creating a cold archive
```bash
# Full archive without encrypted key bundle
$ fieldwitness archive export --output archive_20260401.zip
# Include encrypted key bundle (will prompt for passphrase)
$ fieldwitness archive export --include-keys --output archive_20260401.zip
```
> **Warning:** If you include the encrypted key bundle, store the passphrase separately
> from the archive media. Write it on paper and keep it in a different physical location.
### When to create cold archives
- At regular intervals (weekly or monthly) as part of your backup strategy
- Before key rotation (locks the existing chain state in the archive)
- Before traveling with the device
- Before anticipated risk events (raids, border crossings, legal proceedings)
- When archiving a completed investigation
### Restoring from a cold archive
On a fresh FieldWitness instance:
```bash
$ fieldwitness init
$ fieldwitness archive import archive_20260401.zip
```
### Long-term archival best practices
1. Store archives on at least two separate physical media (USB drives, optical discs)
2. Keep one copy offsite (safe deposit box, trusted third party in a different jurisdiction)
3. Include the encrypted key bundle in the archive with a strong passphrase
4. Periodically verify archive integrity: unzip and run `python verify.py`
5. The `ALGORITHMS.txt` file documents every algorithm and parameter used, so a verifier
can be written from scratch even if FieldWitness no longer exists
### The ALGORITHMS.txt file
This file documents every cryptographic algorithm, parameter, and format used:
- **Signing**: Ed25519 (RFC 8032) -- 32-byte public keys, 64-byte signatures
- **Hashing**: SHA-256 for content and chain linkage; pHash and dHash for perceptual image matching
- **Encryption (key bundle)**: AES-256-GCM with Argon2id key derivation (time_cost=4, memory_cost=256MB, parallelism=4)
- **Chain format**: Append-only binary log with uint32 BE length prefixes and CBOR (RFC 8949) records
- **Attestation log**: Attest binary log format
---
## Selective Disclosure
Selective disclosure produces a verifiable proof for specific chain records while keeping
others redacted. Designed for legal discovery, court orders, and FOIA responses.
### How it works
Selected records are included in full (content hash, content type, signature, metadata,
signer public key). Non-selected records appear only as their record hash and chain index.
The complete hash chain is included so a third party can verify that the disclosed records
are part of an unbroken chain without seeing the contents of other records.
### Creating a selective disclosure
```bash
# Disclose records at chain indices 5, 12, and 47
$ fieldwitness chain disclose --indices 5,12,47 --output disclosure.json
```
### Disclosure output format
```json
{
"proof_version": "1",
"chain_state": {
"chain_id": "a1b2c3...",
"head_index": 100,
"record_count": 101
},
"selected_records": [
{
"chain_index": 5,
"content_hash": "...",
"content_type": "attest/attestation-v1",
"prev_hash": "...",
"record_hash": "...",
"signer_pubkey": "...",
"signature": "...",
"claimed_ts": 1711900000000000,
"metadata": {}
}
],
"redacted_count": 98,
"hash_chain": [
{"chain_index": 0, "record_hash": "...", "prev_hash": "..."},
{"chain_index": 1, "record_hash": "...", "prev_hash": "..."}
]
}
```
### Verifying a selective disclosure
A third party can verify:
1. **Chain linkage**: each entry in `hash_chain` has a `prev_hash` that matches the
`record_hash` of the previous entry
2. **Selected record integrity**: each selected record's `record_hash` matches its position
in the hash chain
3. **Signature validity**: each selected record's Ed25519 signature is valid for its
canonical byte representation
### When to use selective disclosure vs. evidence packages
| Need | Use |
|---|---|
| Hand specific images to a lawyer | Evidence package |
| Respond to a court order for specific records | Selective disclosure |
| Full-state backup for long-term preservation | Cold archive |
| Share attestations with a partner organization | Federation bundle |
---
## Chain Anchoring for Evidence
External timestamp anchoring strengthens evidence by proving that the chain existed before
a given time. A single anchor for the chain head implicitly timestamps every record that
preceded it, because the chain is append-only with hash linkage.
### RFC 3161 automated anchoring
If the device has internet access (even temporarily):
```bash
$ fieldwitness chain anchor --tsa https://freetsa.org/tsr
```
This sends the chain head digest to a Timestamping Authority, receives a signed timestamp
token, and saves both as a JSON file under `~/.fwmetadata/chain/anchors/`. The TSA token is a
cryptographically signed proof from a third party that the hash existed at the stated time.
This is legally stronger than a self-asserted timestamp.
### Manual anchoring (airgapped)
Without `--tsa`:
```bash
$ fieldwitness chain anchor
```
This prints a compact text block. Publish it to any external witness:
- Tweet or public social media post (timestamped by the platform)
- Email to a trusted third party (timestamped by the mail server)
- Newspaper classified advertisement
- Bitcoin OP_RETURN transaction
- Notarized document
### Anchoring strategy for legal proceedings
1. Anchor the chain before disclosing evidence to any party
2. Anchor at regular intervals (daily or weekly) to establish a timeline
3. Anchor before and after major events in an investigation
4. Anchor before key rotation
5. Save anchor files alongside key backups on separate physical media
---
## Legal Discovery Workflow
For responding to a court order, subpoena, or legal discovery request:
1. **Selective disclosure** (`fieldwitness chain disclose`) when the request specifies particular
records and you must not reveal the full chain
2. **Evidence package** when the request requires original images with verification
capability
3. **Cold archive** when full preservation is required (e.g., an entire investigation)
All three formats include standalone verification scripts so the receiving party does not
need FieldWitness installed. The verification scripts require only Python 3.11+ and the
`cryptography` pip package.
> **Note:** Consult with legal counsel before producing evidence from FieldWitness. The selective
> disclosure mechanism is designed to support legal privilege and proportionality, but its
> application depends on your jurisdiction and the specific legal context.