Add client config export command
This commit is contained in:
10
README.md
10
README.md
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
72
src/cli.cpp
72
src/cli.cpp
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user