Add client config export command

This commit is contained in:
server
2026-04-14 11:26:44 +02:00
parent 59262f1691
commit 075668d188
3 changed files with 98 additions and 1 deletions

View File

@@ -22,6 +22,7 @@ with.
- `m2pack list`
- `m2pack verify`
- `m2pack extract`
- `m2pack export-client-config`
## Build
@@ -68,6 +69,15 @@ Extract:
--key keys/master.key
```
Export a client config header for `m2dev-client-src/src/PackLib/M2PackKeys.h`:
```bash
./build/m2pack export-client-config \
--key keys/master.key \
--public-key keys/signing.pub \
--output /path/to/m2dev-client-src/src/PackLib/M2PackKeys.h
```
## Format summary
- Single archive file with a fixed header

View File

@@ -19,6 +19,23 @@ tool.
- 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 \
--output /path/to/m2dev-client-src/src/PackLib/M2PackKeys.h
```
That keeps loader constants aligned with the archive builder.
## Runtime validation
Minimum validation:

View File

@@ -102,7 +102,8 @@ void print_usage()
<< " build --input <dir> --output <file> --key <hex-file> --sign-secret-key <hex-file> [--json]\n"
<< " list --archive <file> [--json]\n"
<< " verify --archive <file> [--public-key <hex-file>] [--key <hex-file>] [--json]\n"
<< " extract --archive <file> --output <dir> --key <hex-file> [--json]\n";
<< " extract --archive <file> --output <dir> --key <hex-file> [--json]\n"
<< " export-client-config --key <hex-file> --public-key <hex-file> --output <file> [--json]\n";
}
void command_keygen(const ParsedArgs& args)
@@ -261,6 +262,70 @@ void command_extract(const ParsedArgs& args)
std::cout << "Extracted " << archive.entries.size() << " files\n";
}
void command_export_client_config(const ParsedArgs& args)
{
const auto master = load_hex_file(require_option(args, "key"));
const auto public_key = load_hex_file(require_option(args, "public-key"));
const auto output_path = require_option(args, "output");
if (master.size() != kAeadKeySize)
{
fail("Master key must be 32 bytes");
}
if (public_key.size() != crypto_sign_PUBLICKEYBYTES)
{
fail("Signing public key has invalid size");
}
auto render_array = [](const std::vector<std::uint8_t>& bytes) {
std::ostringstream out;
for (std::size_t i = 0; i < bytes.size(); ++i)
{
if (i % 8 == 0)
{
out << "\n\t";
}
out << "0x" << to_hex(&bytes[i], 1);
if (i + 1 != bytes.size())
{
out << ", ";
}
}
out << "\n";
return out.str();
};
std::ostringstream header;
header
<< "#pragma once\n\n"
<< "#include <array>\n"
<< "#include <cstdint>\n\n"
<< "// Generated by m2pack export-client-config.\n"
<< "// Do not edit manually.\n\n"
<< "constexpr std::array<uint8_t, M2PACK_KEY_SIZE> M2PACK_MASTER_KEY = {"
<< render_array(master)
<< "};\n\n"
<< "constexpr std::array<uint8_t, M2PACK_PUBLIC_KEY_SIZE> M2PACK_SIGN_PUBLIC_KEY = {"
<< render_array(public_key)
<< "};\n";
const auto text = header.str();
write_file(output_path, std::vector<std::uint8_t>(text.begin(), text.end()));
if (args.json)
{
std::cout
<< "{"
<< "\"ok\":true,"
<< "\"output\":\"" << json_escape(output_path) << "\""
<< "}\n";
return;
}
std::cout << "Wrote client config to " << output_path << "\n";
}
} // namespace
int run_cli(int argc, char** argv)
@@ -300,6 +365,11 @@ int run_cli(int argc, char** argv)
command_extract(args);
return 0;
}
if (args.command == "export-client-config")
{
command_export_client_config(args);
return 0;
}
if (args.command == "help" || args.command == "--help" || args.command == "-h")
{
print_usage();