ui基本完毕,修了一大把的bug
This commit is contained in:
@@ -12,26 +12,50 @@ public static class AllyHeroDeployLedgerStorage
|
||||
private const string BackupFileName = ".ahd.bak";
|
||||
private const string TempFileName = ".ahd.tmp";
|
||||
|
||||
private static string VaultDirectoryPath => Path.Combine(Application.persistentDataPath, VaultDirectoryName);
|
||||
private static string VaultDirectoryPath => Path.Combine(SaveIdentityUtility.GetCanonicalPersistentRoot(), VaultDirectoryName);
|
||||
private static string MainFilePath => Path.Combine(VaultDirectoryPath, MainFileName);
|
||||
private static string BackupFilePath => Path.Combine(VaultDirectoryPath, BackupFileName);
|
||||
private static string TempFilePath => Path.Combine(VaultDirectoryPath, TempFileName);
|
||||
|
||||
public static bool HasExistingSaveFile()
|
||||
{
|
||||
return File.Exists(MainFilePath) || File.Exists(BackupFilePath);
|
||||
var mainCandidates = SaveIdentityUtility.GetVaultFilePathVariants(MainFileName);
|
||||
for (int i = 0; i < mainCandidates.Count; i++)
|
||||
{
|
||||
if (File.Exists(mainCandidates[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var backupCandidates = SaveIdentityUtility.GetVaultFilePathVariants(BackupFileName);
|
||||
for (int i = 0; i < backupCandidates.Count; i++)
|
||||
{
|
||||
if (File.Exists(backupCandidates[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryLoad(out AllyHeroDeployLedgerPayload payload)
|
||||
{
|
||||
payload = CreateDefaultPayload();
|
||||
|
||||
if (TryReadPayload(MainFilePath, out payload))
|
||||
if (TryReadPayloadFromVariants(MainFileName, out payload))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (TryReadPayload(BackupFilePath, out payload))
|
||||
if (TryReadPayloadFromVariants(BackupFileName, out payload))
|
||||
{
|
||||
TrySave(payload);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (PlayerProgressBackupService.TryRestoreAllyHeroDeploy(out payload))
|
||||
{
|
||||
TrySave(payload);
|
||||
return true;
|
||||
@@ -60,6 +84,7 @@ public static class AllyHeroDeployLedgerStorage
|
||||
File.Copy(TempFilePath, MainFilePath, true);
|
||||
TryHidePath(MainFilePath);
|
||||
File.Delete(TempFilePath);
|
||||
PlayerProgressBackupService.SaveAllyHeroDeploy(payload);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -96,17 +121,32 @@ public static class AllyHeroDeployLedgerStorage
|
||||
return false;
|
||||
}
|
||||
|
||||
string expectedSignature = ComputeSignature(envelope.payload);
|
||||
if (!string.Equals(expectedSignature, envelope.signature, StringComparison.Ordinal))
|
||||
if (!TryValidateSignature(envelope.payload, envelope.signature))
|
||||
{
|
||||
Debug.LogWarning("[AllyHeroDeployLedgerStorage] Save signature mismatch. Possible tampering detected.");
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] encryptedBytes = Convert.FromBase64String(envelope.payload);
|
||||
byte[] plainBytes = XorTransform(encryptedBytes, BuildKeyBytes());
|
||||
string payloadJson = Encoding.UTF8.GetString(plainBytes);
|
||||
AllyHeroDeployLedgerPayload loadedPayload = JsonUtility.FromJson<AllyHeroDeployLedgerPayload>(payloadJson);
|
||||
AllyHeroDeployLedgerPayload loadedPayload = null;
|
||||
var identifierVariants = SaveIdentityUtility.GetApplicationIdentifierVariants();
|
||||
for (int i = 0; i < identifierVariants.Count; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] plainBytes = XorTransform(encryptedBytes, BuildKeyBytes(identifierVariants[i]));
|
||||
string payloadJson = Encoding.UTF8.GetString(plainBytes);
|
||||
loadedPayload = JsonUtility.FromJson<AllyHeroDeployLedgerPayload>(payloadJson);
|
||||
if (loadedPayload != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (loadedPayload == null)
|
||||
{
|
||||
return false;
|
||||
@@ -122,6 +162,21 @@ public static class AllyHeroDeployLedgerStorage
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryReadPayloadFromVariants(string fileName, out AllyHeroDeployLedgerPayload payload)
|
||||
{
|
||||
payload = CreateDefaultPayload();
|
||||
var candidates = SaveIdentityUtility.GetVaultFilePathVariants(fileName);
|
||||
for (int i = 0; i < candidates.Count; i++)
|
||||
{
|
||||
if (TryReadPayload(candidates[i], out payload))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string BuildEnvelopeJson(AllyHeroDeployLedgerPayload payload)
|
||||
{
|
||||
payload.lastUpdatedUtcTicks = DateTime.UtcNow.Ticks;
|
||||
@@ -141,7 +196,7 @@ public static class AllyHeroDeployLedgerStorage
|
||||
|
||||
private static string ComputeSignature(string payloadBase64)
|
||||
{
|
||||
string signText = payloadBase64 + "|" + Application.identifier + "|" + SecretSeed + "|" + SystemInfo.deviceUniqueIdentifier;
|
||||
string signText = payloadBase64 + "|" + SaveIdentityUtility.GetPrimaryApplicationIdentifier() + "|" + SecretSeed + "|" + SystemInfo.deviceUniqueIdentifier;
|
||||
using (SHA256 sha = SHA256.Create())
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(signText);
|
||||
@@ -151,14 +206,45 @@ public static class AllyHeroDeployLedgerStorage
|
||||
}
|
||||
|
||||
private static byte[] BuildKeyBytes()
|
||||
{
|
||||
return BuildKeyBytes(SaveIdentityUtility.GetPrimaryApplicationIdentifier());
|
||||
}
|
||||
|
||||
private static byte[] BuildKeyBytes(string applicationIdentifier)
|
||||
{
|
||||
using (SHA256 sha = SHA256.Create())
|
||||
{
|
||||
string seed = Application.identifier + "|" + SystemInfo.deviceUniqueIdentifier + "|" + SecretSeed;
|
||||
string seed = applicationIdentifier + "|" + SystemInfo.deviceUniqueIdentifier + "|" + SecretSeed;
|
||||
return sha.ComputeHash(Encoding.UTF8.GetBytes(seed));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryValidateSignature(string payloadBase64, string signature)
|
||||
{
|
||||
var identifierVariants = SaveIdentityUtility.GetApplicationIdentifierVariants();
|
||||
for (int i = 0; i < identifierVariants.Count; i++)
|
||||
{
|
||||
string expectedSignature = ComputeSignature(payloadBase64, identifierVariants[i]);
|
||||
if (string.Equals(expectedSignature, signature, StringComparison.Ordinal))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string ComputeSignature(string payloadBase64, string applicationIdentifier)
|
||||
{
|
||||
string signText = payloadBase64 + "|" + applicationIdentifier + "|" + SecretSeed + "|" + SystemInfo.deviceUniqueIdentifier;
|
||||
using (SHA256 sha = SHA256.Create())
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(signText);
|
||||
byte[] hash = sha.ComputeHash(bytes);
|
||||
return Convert.ToBase64String(hash);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] XorTransform(byte[] source, byte[] key)
|
||||
{
|
||||
byte[] result = new byte[source.Length];
|
||||
|
||||
Reference in New Issue
Block a user