67 lines
1.7 KiB
Markdown
67 lines
1.7 KiB
Markdown
# Format
|
|
|
|
`m2pack-secure` uses a single-file archive format optimized for runtime loading.
|
|
|
|
## Header
|
|
|
|
Fixed-size header at the start of the archive:
|
|
|
|
- magic: `M2PACK2`
|
|
- format version
|
|
- manifest offset
|
|
- manifest size
|
|
- manifest hash: `BLAKE2b-256`
|
|
- manifest signature: `Ed25519`
|
|
|
|
The header is intentionally tiny and stable so the loader can validate it before
|
|
touching asset payloads.
|
|
|
|
## Manifest
|
|
|
|
The manifest stores:
|
|
|
|
- normalized relative path
|
|
- data offset
|
|
- original size
|
|
- stored size
|
|
- compression algorithm
|
|
- per-file nonce
|
|
- plaintext hash
|
|
|
|
The manifest is signed as a whole. Runtime validation should always happen in
|
|
this order:
|
|
|
|
1. read header
|
|
2. read manifest
|
|
3. compare manifest hash
|
|
4. verify manifest signature
|
|
5. resolve entry by path
|
|
6. decrypt and decompress asset
|
|
7. optionally hash plaintext for debug or strict mode
|
|
|
|
## Data
|
|
|
|
Each file payload is:
|
|
|
|
1. compressed with `zstd` when it produces a meaningful size win
|
|
2. otherwise stored as plaintext bytes
|
|
3. encrypted with `XChaCha20-Poly1305`
|
|
4. stored in-place in the archive
|
|
|
|
The file path is used as associated data so path tampering invalidates the
|
|
payload authentication tag.
|
|
|
|
## Security model
|
|
|
|
This format is designed to prevent trivial unpacking and silent tampering. It is
|
|
not a claim of absolute secrecy, because the client still contains the runtime
|
|
key path and loader logic.
|
|
|
|
Recommended production posture:
|
|
|
|
- do not hardcode the final master key as a trivial static array
|
|
- derive a session key in the launcher when possible
|
|
- keep the signing public key in the client
|
|
- keep the signing secret key only in CI or the release workstation
|
|
- rotate the master content key on format-breaking releases
|