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.
39 lines
1.9 KiB
C#
39 lines
1.9 KiB
C#
namespace Metin2Launcher.Config;
|
|
|
|
/// <summary>
|
|
/// Hardcoded configuration for the launcher MVP.
|
|
/// These values are deliberately not loaded from a config file — they are compile-time
|
|
/// constants so a tampered local config cannot redirect updates.
|
|
/// </summary>
|
|
public static class LauncherConfig
|
|
{
|
|
public const string ManifestUrl = "https://updates.jakubkadlec.dev/manifest.json";
|
|
public const string SignatureUrl = "https://updates.jakubkadlec.dev/manifest.json.sig";
|
|
public const string BlobBaseUrl = "https://updates.jakubkadlec.dev/files";
|
|
public const string VelopackFeedUrl = "https://updates.jakubkadlec.dev/launcher";
|
|
public const string GameExecutable = "Metin2.exe";
|
|
|
|
/// <summary>
|
|
/// Ed25519 public key used to verify the manifest signature.
|
|
///
|
|
/// 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 = "1d2b63751ea0e0354d28e7eb4ec175919a01518b0bcf5878f0a3aa8e7c6ce2bc";
|
|
|
|
public static readonly TimeSpan ManifestFetchTimeout = TimeSpan.FromSeconds(10);
|
|
public static readonly TimeSpan BlobFetchTimeout = TimeSpan.FromSeconds(60);
|
|
public static readonly TimeSpan TotalUpdateTimeout = TimeSpan.FromMinutes(30);
|
|
|
|
public const int MaxBlobRetries = 3;
|
|
|
|
/// <summary>Name of the directory under the client root that holds launcher state.</summary>
|
|
public const string StateDirName = ".updates";
|
|
|
|
/// <summary>Name of the staging directory under the state directory.</summary>
|
|
public const string StagingDirName = "staging";
|
|
}
|