客户端rsa,冗余清理,bug修复,安卓build问题

This commit is contained in:
FloatGaming
2026-07-14 01:43:49 +08:00
parent fd22501f71
commit f8985d91d2
682 changed files with 4595 additions and 11216 deletions
@@ -19,6 +19,7 @@ public static class SecureSaveVault
{
private const string SecretSeed = "ban_total.secure_save_v2";
private const string VaultDirectoryName = ".cache_bridge";
private const string RecoveryDirectoryName = ".save_recovery";
private static bool s_dpapiInitialized;
private static bool s_dpapiSupported;
private static MethodInfo s_dpapiProtectMethod;
@@ -30,6 +31,11 @@ public static class SecureSaveVault
get { return Path.Combine(SaveIdentityUtility.GetCanonicalPersistentRoot(), VaultDirectoryName); }
}
private static string RecoveryDirectoryPath
{
get { return Path.Combine(SaveIdentityUtility.GetCanonicalPersistentRoot(), RecoveryDirectoryName); }
}
public static bool SaveJson<T>(string category, string key, T data, string legacyPlainPath = null)
{
if (!typeof(T).IsValueType && (object)data == null)
@@ -103,6 +109,7 @@ public static class SecureSaveVault
File.Copy(tempPath, mainPath, true);
TryHidePath(mainPath);
File.Delete(tempPath);
TrySaveRecoveryCopy(category, key, json);
DeleteLegacyPlainFile(legacyPlainPath);
return true;
}
@@ -126,6 +133,12 @@ public static class SecureSaveVault
return true;
}
if (TryLoadFromRecoveryCopies(category, key, out json))
{
SaveRawJson(category, key, json, legacyPlainPath);
return true;
}
if (!string.IsNullOrEmpty(legacyPlainPath) && File.Exists(legacyPlainPath))
{
try
@@ -236,6 +249,47 @@ public static class SecureSaveVault
return Directory.GetFiles(categoryDirectory, "*.dat", SearchOption.TopDirectoryOnly).Length;
}
public static bool HasAnyRecoverableState(string category, string key, string legacyPlainPath = null)
{
if (string.IsNullOrWhiteSpace(category) || string.IsNullOrWhiteSpace(key))
{
return false;
}
IReadOnlyList<string> roots = SaveIdentityUtility.GetPersistentRootVariants(legacyPlainPath);
IReadOnlyList<string> identifierVariants = SaveIdentityUtility.GetApplicationIdentifierVariants();
for (int rootIndex = 0; rootIndex < roots.Count; rootIndex++)
{
string root = roots[rootIndex];
if (string.IsNullOrWhiteSpace(root))
{
continue;
}
for (int variantIndex = 0; variantIndex < identifierVariants.Count; variantIndex++)
{
string applicationIdentifier = identifierVariants[variantIndex];
if (File.Exists(GetFilePathForRoot(root, category, key, ".dat", applicationIdentifier))
|| File.Exists(GetFilePathForRoot(root, category, key, ".bak", applicationIdentifier)))
{
return true;
}
}
}
IReadOnlyList<string> recoveryCandidates = GetRecoveryFilePathVariants(category, key);
for (int i = 0; i < recoveryCandidates.Count; i++)
{
string path = recoveryCandidates[i];
if (!string.IsNullOrWhiteSpace(path) && File.Exists(path))
{
return true;
}
}
return !string.IsNullOrEmpty(legacyPlainPath) && File.Exists(legacyPlainPath);
}
private static bool TryReadEncryptedFile(string category, string key, string filePath, out string json)
{
json = null;
@@ -616,6 +670,117 @@ public static class SecureSaveVault
return Path.Combine(categoryDirectory, "." + safeKey + extension);
}
private static bool TryLoadFromRecoveryCopies(string category, string key, out string json)
{
json = null;
IReadOnlyList<string> candidates = GetRecoveryFilePathVariants(category, key);
for (int i = 0; i < candidates.Count; i++)
{
string path = candidates[i];
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
{
continue;
}
try
{
string loaded = File.ReadAllText(path, Encoding.UTF8);
if (string.IsNullOrWhiteSpace(loaded))
{
continue;
}
json = loaded;
return true;
}
catch (Exception ex)
{
Debug.LogWarning($"[SecureSaveVault] Recovery read failed ({path}): {ex.Message}");
}
}
return false;
}
private static void TrySaveRecoveryCopy(string category, string key, string json)
{
if (string.IsNullOrWhiteSpace(category) || string.IsNullOrWhiteSpace(key) || json == null)
{
return;
}
try
{
Directory.CreateDirectory(RecoveryDirectoryPath);
string recoveryPath = GetRecoveryFilePath(category, key);
string backupPath = recoveryPath + ".bak";
string tempPath = recoveryPath + ".tmp";
File.WriteAllText(tempPath, json, Encoding.UTF8);
if (File.Exists(recoveryPath))
{
File.Copy(recoveryPath, backupPath, true);
}
File.Copy(tempPath, recoveryPath, true);
File.Delete(tempPath);
}
catch (Exception ex)
{
Debug.LogWarning($"[SecureSaveVault] Recovery mirror save failed ({category}/{key}): {ex.Message}");
}
}
private static string GetRecoveryFilePath(string category, string key)
{
string safeName = ShortHash("recovery|" + category + "|" + key);
return Path.Combine(RecoveryDirectoryPath, safeName + ".json");
}
private static IReadOnlyList<string> GetRecoveryFilePathVariants(string category, string key)
{
var result = new List<string>();
if (string.IsNullOrWhiteSpace(category) || string.IsNullOrWhiteSpace(key))
{
return result;
}
string safeName = ShortHash("recovery|" + category + "|" + key) + ".json";
string safeBackupName = safeName + ".bak";
IReadOnlyList<string> roots = SaveIdentityUtility.GetPersistentRootVariants();
for (int i = 0; i < roots.Count; i++)
{
string root = roots[i];
if (string.IsNullOrWhiteSpace(root))
{
continue;
}
AddDistinctPath(result, Path.Combine(root, RecoveryDirectoryName, safeName));
AddDistinctPath(result, Path.Combine(root, RecoveryDirectoryName, safeBackupName));
}
return result;
}
private static void AddDistinctPath(List<string> target, string value)
{
if (target == null || string.IsNullOrWhiteSpace(value))
{
return;
}
for (int i = 0; i < target.Count; i++)
{
if (string.Equals(target[i], value, StringComparison.OrdinalIgnoreCase))
{
return;
}
}
target.Add(value);
}
private static void DeleteLegacyPlainFile(string legacyPlainPath)
{
if (string.IsNullOrEmpty(legacyPlainPath) || !File.Exists(legacyPlainPath))