Files
m2pack-secure/docs/client-integration.md
2026-04-14 12:26:22 +02:00

131 lines
3.3 KiB
Markdown

# Client integration
Your current client already has a custom `PackLib` using `zstd` and
`XChaCha20`. This project should become the next iteration, not a parallel dead
tool.
## Suggested migration
1. Keep the current `PackManager` interface stable.
2. Add a new loader beside the current pack code, for example:
- `src/PackLib/M2PackArchive.h`
- `src/PackLib/M2PackArchive.cpp`
3. Route `CPackManager::AddPack()` by extension:
- legacy format for old `.pack`
- new format for `.m2p`
4. Embed only the signing public key in the client.
5. Resolve the content decryption key from runtime delivery:
- launcher-provided memory
- machine-bound cache
- or a derived release secret
## Client key header
For the current implementation, the client expects:
- `src/PackLib/M2PackKeys.h`
Generate it from the release key material with:
```bash
m2pack export-client-config \
--key keys/master.key \
--public-key keys/signing.pub \
--key-id 1 \
--output /path/to/m2dev-client-src/src/PackLib/M2PackKeys.h
```
That keeps loader constants aligned with the archive builder.
Important:
- the generated client header no longer embeds the real master key
- `.m2p` loading now requires a runtime master key
- the runtime master key must match the archive `key_id`
- if a `.m2p` file exists and fails validation or runtime key resolution, the client should not silently fall back to `.pck`
## Runtime validation
Minimum validation:
- verify header magic and version
- compare manifest hash
- verify manifest signature
- reject duplicate paths
- reject path traversal
- verify AEAD tag before decompression
## Launcher key delivery
The client now supports runtime key overrides and no longer has to rely only on
the compiled fallback key.
Supported inputs, highest priority last:
1. shared memory mapping
2. environment variables
3. command line arguments
### Command line
```text
--m2pack-key-hex <64-hex-master-key>
--m2pack-pubkey-hex <64-hex-public-key>
--m2pack-key-map <mapping-name>
--m2pack-key-id <integer>
```
### Environment
```text
M2PACK_MASTER_KEY_HEX
M2PACK_SIGN_PUBKEY_HEX
M2PACK_KEY_MAP
M2PACK_KEY_ID
```
### Shared memory
Default mapping name:
```text
Local\M2PackSharedKeys
```
Binary layout:
```c
struct M2PackSharedKeys {
char magic[8]; // "M2KEYS1\0"
uint32_t version; // 1
uint32_t flags; // reserved
uint32_t key_id; // runtime master key slot
uint8_t master_key[32];
uint8_t sign_public_key[32];
};
```
Recommended production path:
- launcher fetches or unwraps the current content key
- launcher creates the shared mapping
- launcher starts the client with `--m2pack-key-map Local\\M2PackSharedKeys`
- client reads runtime keys during startup
- client rejects `.m2p` loading if the runtime master key is missing
## Loader notes
- Use memory-mapped I/O for the archive.
- Keep a path-to-entry map in lowercase normalized form.
- Decrypt per request, not by unpacking the full archive.
- Keep a small decompression scratch buffer pool if the client reads in parallel.
## Release model
- `master.key`: private content encryption key
- `signing.key`: private release signing key
- `signing.pub`: embedded client verifier key
The signing key belongs in CI or a secured release box. The public key belongs
in the client binary or in a protected launcher manifest.