|
|
@ -25,21 +25,22 @@ public class GlobalUserSecrets |
|
|
|
|
|
|
|
|
|
|
|
public Dictionary<string, string> PatreonCookies { get; set; } = new(); |
|
|
|
public Dictionary<string, string> PatreonCookies { get; set; } = new(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public string? CivitApiToken { get; set; } |
|
|
|
|
|
|
|
|
|
|
|
private static string? GetComputerSid() |
|
|
|
private static string? GetComputerSid() |
|
|
|
{ |
|
|
|
{ |
|
|
|
var deviceId = new DeviceIdBuilder() |
|
|
|
var deviceId = new DeviceIdBuilder() |
|
|
|
.AddMachineName() |
|
|
|
.AddMachineName() |
|
|
|
.AddOsVersion() |
|
|
|
.AddOsVersion() |
|
|
|
.OnWindows(windows => windows |
|
|
|
.OnWindows( |
|
|
|
.AddProcessorId() |
|
|
|
windows => |
|
|
|
.AddMotherboardSerialNumber() |
|
|
|
windows |
|
|
|
.AddSystemDriveSerialNumber()) |
|
|
|
.AddProcessorId() |
|
|
|
.OnLinux(linux => linux |
|
|
|
.AddMotherboardSerialNumber() |
|
|
|
.AddMotherboardSerialNumber() |
|
|
|
.AddSystemDriveSerialNumber() |
|
|
|
.AddSystemDriveSerialNumber()) |
|
|
|
) |
|
|
|
.OnMac(mac => mac |
|
|
|
.OnLinux(linux => linux.AddMotherboardSerialNumber().AddSystemDriveSerialNumber()) |
|
|
|
.AddSystemDriveSerialNumber() |
|
|
|
.OnMac(mac => mac.AddSystemDriveSerialNumber().AddPlatformSerialNumber()) |
|
|
|
.AddPlatformSerialNumber()) |
|
|
|
|
|
|
|
.ToString(); |
|
|
|
.ToString(); |
|
|
|
|
|
|
|
|
|
|
|
return deviceId; |
|
|
|
return deviceId; |
|
|
@ -63,14 +64,24 @@ public class GlobalUserSecrets |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static KeyInfo DeriveKeyWithSalt(SecureString password, int saltLength, int iterations, int keyLength) |
|
|
|
private static KeyInfo DeriveKeyWithSalt( |
|
|
|
|
|
|
|
SecureString password, |
|
|
|
|
|
|
|
int saltLength, |
|
|
|
|
|
|
|
int iterations, |
|
|
|
|
|
|
|
int keyLength |
|
|
|
|
|
|
|
) |
|
|
|
{ |
|
|
|
{ |
|
|
|
var salt = RandomNumberGenerator.GetBytes(saltLength); |
|
|
|
var salt = RandomNumberGenerator.GetBytes(saltLength); |
|
|
|
var key = DeriveKey(password, salt, iterations, keyLength); |
|
|
|
var key = DeriveKey(password, salt, iterations, keyLength); |
|
|
|
return new KeyInfo(key, salt, iterations); |
|
|
|
return new KeyInfo(key, salt, iterations); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static byte[] DeriveKey(SecureString password, byte[] salt, int iterations, int keyLength) |
|
|
|
private static byte[] DeriveKey( |
|
|
|
|
|
|
|
SecureString password, |
|
|
|
|
|
|
|
byte[] salt, |
|
|
|
|
|
|
|
int iterations, |
|
|
|
|
|
|
|
int keyLength |
|
|
|
|
|
|
|
) |
|
|
|
{ |
|
|
|
{ |
|
|
|
var ptr = Marshal.SecureStringToBSTR(password); |
|
|
|
var ptr = Marshal.SecureStringToBSTR(password); |
|
|
|
try |
|
|
|
try |
|
|
@ -102,8 +113,7 @@ public class GlobalUserSecrets |
|
|
|
|
|
|
|
|
|
|
|
private static (byte[], byte[]) EncryptBytes(byte[] data) |
|
|
|
private static (byte[], byte[]) EncryptBytes(byte[] data) |
|
|
|
{ |
|
|
|
{ |
|
|
|
var keyInfo = |
|
|
|
var keyInfo = DeriveKeyWithSalt(GetComputerKeyPhrase(), SaltSize, Iterations, KeySize); |
|
|
|
DeriveKeyWithSalt(GetComputerKeyPhrase(), SaltSize, Iterations, KeySize); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using var aes = Aes.Create(); |
|
|
|
using var aes = Aes.Create(); |
|
|
|
aes.Key = keyInfo.Key; |
|
|
|
aes.Key = keyInfo.Key; |
|
|
@ -117,8 +127,7 @@ public class GlobalUserSecrets |
|
|
|
|
|
|
|
|
|
|
|
private static byte[] DecryptBytes(IReadOnlyCollection<byte> encryptedData, byte[] salt) |
|
|
|
private static byte[] DecryptBytes(IReadOnlyCollection<byte> encryptedData, byte[] salt) |
|
|
|
{ |
|
|
|
{ |
|
|
|
var key = |
|
|
|
var key = DeriveKey(GetComputerKeyPhrase(), salt, Iterations, KeySize); |
|
|
|
DeriveKey(GetComputerKeyPhrase(), salt, Iterations, KeySize); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using var aes = Aes.Create(); |
|
|
|
using var aes = Aes.Create(); |
|
|
|
aes.Key = key; |
|
|
|
aes.Key = key; |
|
|
@ -136,11 +145,19 @@ public class GlobalUserSecrets |
|
|
|
var (encrypted, salt) = EncryptBytes(json); |
|
|
|
var (encrypted, salt) = EncryptBytes(json); |
|
|
|
// Prepend salt to encrypted json |
|
|
|
// Prepend salt to encrypted json |
|
|
|
var fileBytes = salt.Concat(encrypted).ToArray(); |
|
|
|
var fileBytes = salt.Concat(encrypted).ToArray(); |
|
|
|
|
|
|
|
|
|
|
|
File.WriteAllBytes(fileBytes); |
|
|
|
File.WriteAllBytes(fileBytes); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static GlobalUserSecrets? LoadFromFile() |
|
|
|
public static GlobalUserSecrets? LoadFromFile() |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
File.Info.Refresh(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!File.Exists) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return new GlobalUserSecrets(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var fileBytes = File.ReadAllBytes(); |
|
|
|
var fileBytes = File.ReadAllBytes(); |
|
|
|
|
|
|
|
|
|
|
|
// Get salt from start of file |
|
|
|
// Get salt from start of file |
|
|
|