3.5 KiB
3.5 KiB
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
- Keep the current
PackManagerinterface stable. - Add a new loader beside the current pack code, for example:
src/PackLib/M2PackArchive.hsrc/PackLib/M2PackArchive.cpp
- Route
CPackManager::AddPack()by extension:- legacy format for old
.pack - new format for
.m2p
- legacy format for old
- Embed only the signing public key in the client.
- 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:
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
.m2ploading now requires a runtime master key- the runtime master key must match the archive
key_id - if a
.m2pfile 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
- verify plaintext hash only in debug or explicit strict mode
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:
- shared memory mapping
- environment variables
- command line arguments
Command line
--m2pack-key-hex <64-hex-master-key>
--m2pack-pubkey-hex <64-hex-public-key>
--m2pack-key-map <mapping-name>
--m2pack-key-id <integer>
--m2pack-strict-hash [0|1]
Environment
M2PACK_MASTER_KEY_HEX
M2PACK_SIGN_PUBKEY_HEX
M2PACK_KEY_MAP
M2PACK_KEY_ID
M2PACK_STRICT_HASH
Shared memory
Default mapping name:
Local\M2PackSharedKeys
Binary layout:
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
.m2ploading 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.
- Skip plaintext hash verification in release hot paths unless
M2PACK_STRICT_HASHor--m2pack-strict-hashexplicitly enables it.
Release model
master.key: private content encryption keysigning.key: private release signing keysigning.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.