67 lines
2.2 KiB
C#
67 lines
2.2 KiB
C#
using System.Security.Cryptography;
|
|
using System.Text;
|
|
|
|
namespace WxAgent.Core;
|
|
|
|
public enum KeyBindingConfidence
|
|
{
|
|
PageHmacVerified
|
|
}
|
|
|
|
public sealed record DatabaseKeyEvidence(
|
|
string RelativePath,
|
|
string Salt,
|
|
string EncKey,
|
|
int SourceProcessId,
|
|
DateTimeOffset VerifiedAt,
|
|
KeyBindingConfidence Confidence);
|
|
|
|
public sealed record AccountKeySet(
|
|
string AccountRootFingerprint,
|
|
string AccountRootPath,
|
|
string? WechatVersion,
|
|
DateTimeOffset LastSeenAt,
|
|
IReadOnlyList<DatabaseKeyEvidence> Databases);
|
|
|
|
public static class AccountKeySetMerge
|
|
{
|
|
public static IReadOnlyList<AccountKeySet> Merge(
|
|
IReadOnlyList<AccountKeySet> existing,
|
|
IReadOnlyList<AccountKeySet> incoming)
|
|
{
|
|
var accounts = existing.ToDictionary(account => account.AccountRootFingerprint, StringComparer.OrdinalIgnoreCase);
|
|
foreach (var current in incoming)
|
|
{
|
|
if (!accounts.TryGetValue(current.AccountRootFingerprint, out var previous))
|
|
{
|
|
accounts[current.AccountRootFingerprint] = current;
|
|
continue;
|
|
}
|
|
|
|
var databases = previous.Databases.ToDictionary(database => database.RelativePath, StringComparer.OrdinalIgnoreCase);
|
|
foreach (var database in current.Databases)
|
|
{
|
|
databases[database.RelativePath] = database;
|
|
}
|
|
|
|
accounts[current.AccountRootFingerprint] = current with
|
|
{
|
|
WechatVersion = current.WechatVersion ?? previous.WechatVersion,
|
|
Databases = databases.Values.OrderBy(database => database.RelativePath, StringComparer.OrdinalIgnoreCase).ToArray()
|
|
};
|
|
}
|
|
|
|
return accounts.Values.OrderBy(account => account.AccountRootFingerprint, StringComparer.OrdinalIgnoreCase).ToArray();
|
|
}
|
|
}
|
|
|
|
public static class AccountRootFingerprint
|
|
{
|
|
public static string Create(string accountRootPath)
|
|
{
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(accountRootPath);
|
|
var normalized = accountRootPath.Replace('/', '\\').TrimEnd('\\').ToUpperInvariant();
|
|
return Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(normalized))).ToLowerInvariant();
|
|
}
|
|
}
|