-
Notifications
You must be signed in to change notification settings - Fork 742
Expand file tree
/
Copy pathCoreCredentialStore.cs
More file actions
109 lines (100 loc) · 3.38 KB
/
CoreCredentialStore.cs
File metadata and controls
109 lines (100 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
using System.Net;
using System.Security.Cryptography;
using System.Text;
using UniGetUI.Core.Logging;
#if WINDOWS
using Windows.Security.Credentials;
#endif
namespace UniGetUI.Core.Data;
public static class CoreCredentialStore
{
public static NetworkCredential? GetCredential(string resourceName, string userName)
{
string? secret = GetSecret(resourceName, userName);
return secret is null
? null
: new NetworkCredential
{
UserName = userName,
Password = secret,
};
}
public static void SetCredential(string resourceName, string userName, string password)
=> SetSecret(resourceName, userName, password);
public static string? GetSecret(string resourceName, string userName)
{
try
{
#if WINDOWS
var vault = new PasswordVault();
var credential = vault.Retrieve(resourceName, userName);
credential.RetrievePassword();
return credential.Password;
#else
string secretPath = GetSecretPath(resourceName, userName);
return File.Exists(secretPath) ? File.ReadAllText(secretPath) : null;
#endif
}
catch (Exception ex)
{
Logger.Warn($"Unable to retrieve secret for resource '{resourceName}': {ex.Message}");
return null;
}
}
public static void SetSecret(string resourceName, string userName, string secret)
{
try
{
#if WINDOWS
DeleteSecret(resourceName, userName);
var vault = new PasswordVault();
vault.Add(new PasswordCredential(resourceName, userName, secret));
#else
string storageDirectory = GetStorageDirectory();
Directory.CreateDirectory(storageDirectory);
File.WriteAllText(GetSecretPath(resourceName, userName), secret);
#endif
}
catch (Exception ex)
{
Logger.Error($"Unable to persist secret for resource '{resourceName}'");
Logger.Error(ex);
}
}
public static void DeleteSecret(string resourceName, string userName)
{
try
{
#if WINDOWS
var vault = new PasswordVault();
IReadOnlyList<PasswordCredential> credentials = vault.FindAllByResource(resourceName) ?? [];
foreach (PasswordCredential credential in credentials.Where(credential => credential.UserName == userName))
{
vault.Remove(credential);
}
#else
string secretPath = GetSecretPath(resourceName, userName);
if (File.Exists(secretPath))
{
File.Delete(secretPath);
}
#endif
}
catch (Exception ex)
{
Logger.Error($"Unable to delete secret for resource '{resourceName}'");
Logger.Error(ex);
}
}
#if !WINDOWS
private static string GetStorageDirectory()
=> Path.Join(CoreData.UniGetUIDataDirectory, "SecureStorage");
private static string GetSecretPath(string resourceName, string userName)
=> Path.Join(GetStorageDirectory(), GetStableFileName(resourceName, userName));
private static string GetStableFileName(string resourceName, string userName)
{
byte[] hash = SHA256.HashData(Encoding.UTF8.GetBytes($"{resourceName}\n{userName}"));
return Convert.ToHexString(hash) + ".secret";
}
#endif
}