Initial commit: Client Doc docs Server Tools

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ud18010
2026-07-10 10:24:29 +08:00
co-authored by Cursor
commit 7e35d8da31
3374 changed files with 680813 additions and 0 deletions
@@ -0,0 +1,51 @@
using System;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
namespace XGame.MiniGame
{
// 发布产物签名验证(设计 §7):用内置 RSA 公钥(modulus+exponent, base64)验 files.txt 的 digest 签名。
// 公钥未配置(空)时跳过验签(仅本地开发);正式包必须填入与发布方私钥配对的公钥。
// 用 RSAParameters+ImportParametersnetstandard2.0 起即有,Unity mono 普遍支持),避免 ImportFromPem(net5+)。
public static class ClientManifestVerifier
{
// TODO(发布前必填):从发布方 RSA 密钥对导出的公钥分量 base64。
// 例:RSAParameters p = rsa.ExportParameters(false); Modulus=Convert.ToBase64String(p.Modulus); Exponent=Convert.ToBase64String(p.Exponent)("AQAB")
private const string PublicKeyModulusB64 = "";
private const string PublicKeyExponentB64 = "";
public static bool IsConfigured =>
PublicKeyModulusB64.Length > 0 && PublicKeyExponentB64.Length > 0;
// 验 sig(对 digest 的 UTF8 字节做 RSA-SHA256-PKCS1 签名,与发布工具 ManifestSigner.Sign 一致)
public static bool Verify(string digest, byte[] signature)
{
if (!IsConfigured)
{
Debug.LogWarning("[ClientManifestVerifier] 未配置公钥,跳过验签(仅限开发)");
return true;
}
if (signature == null || signature.Length == 0) return false;
try
{
var p = new RSAParameters
{
Modulus = Convert.FromBase64String(PublicKeyModulusB64),
Exponent = Convert.FromBase64String(PublicKeyExponentB64),
};
using (var rsa = RSA.Create())
{
rsa.ImportParameters(p);
return rsa.VerifyData(Encoding.UTF8.GetBytes(digest), signature,
HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
}
catch (Exception e)
{
Debug.LogError("[ClientManifestVerifier] 验签异常: " + e.Message);
return false;
}
}
}
}