launcher: swap placeholder key for real production public key

Replace the MVP placeholder Ed25519 public key with the real one that
corresponds to ~/.config/metin/launcher-signing-key on the release
machine. Update README to document where the private half lives and
how rotation works. Private key is not committed anywhere; the only
code path that touches it is scripts/sign-manifest.py in m2dev-client.
This commit is contained in:
Jan Nedbal
2026-04-14 11:21:07 +02:00
parent cc904fb881
commit a134e7548f
2 changed files with 16 additions and 12 deletions

View File

@@ -74,15 +74,18 @@ tests/Metin2Launcher.Tests/
game assets (~4 GB) are handled by our own patcher code.
- **xunit / xunit.runner.visualstudio** — tests.
## PLACEHOLDER public key
## Signing key
`LauncherConfig.PublicKeyHex` currently contains a **test-only** Ed25519 public
key generated locally during MVP scaffolding:
`LauncherConfig.PublicKeyHex` is the Ed25519 public key that every manifest
must verify against:
```
a8619c11348cb26cdcad9467c5dd44e3fcb40017e9fbcf225ac76ad824422c46
1d2b63751ea0e0354d28e7eb4ec175919a01518b0bcf5878f0a3aa8e7c6ce2bc
```
This MUST be replaced with the real production signing key before the first
public release. The private half of this placeholder was used only to prove
signature wiring works; it is not tied to any real release.
The matching private key lives only on the release machine at
`~/.config/metin/launcher-signing-key` with `chmod 600`, is never committed
to any repo, and is used by `scripts/sign-manifest.py` in the `m2dev-client`
repo to sign `manifest.json` before upload. Rotation is done by shipping a
new launcher binary that embeds the new public key; the rotation flow is
documented in `m2dev-client/docs/update-manager.md`.

View File

@@ -16,12 +16,13 @@ public static class LauncherConfig
/// <summary>
/// Ed25519 public key used to verify the manifest signature.
///
/// PLACEHOLDER — generated with NSec.Cryptography during MVP scaffolding.
/// Must be swapped for the real production key before first public release.
/// The matching private key lives only in the test-generator used locally and
/// IS NOT used to sign any real release.
/// The matching private key lives offline in ~/.config/metin/launcher-signing-key
/// (chmod 600) on the release machine and is never committed to any repo.
/// Manifests are signed with scripts/sign-manifest.py in the m2dev-client repo.
/// Rotation is done by shipping a new launcher binary that embeds the new public
/// key; see docs/update-manager.md for the rotation flow.
/// </summary>
public const string PublicKeyHex = "a8619c11348cb26cdcad9467c5dd44e3fcb40017e9fbcf225ac76ad824422c46";
public const string PublicKeyHex = "1d2b63751ea0e0354d28e7eb4ec175919a01518b0bcf5878f0a3aa8e7c6ce2bc";
public static readonly TimeSpan ManifestFetchTimeout = TimeSpan.FromSeconds(10);
public static readonly TimeSpan BlobFetchTimeout = TimeSpan.FromSeconds(60);