30 lines
1.3 KiB
C#
30 lines
1.3 KiB
C#
|
|
using System.Security.Cryptography;
|
||
|
|
using System.Text;
|
||
|
|
|
||
|
|
namespace VoiceCat.App.Models;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// DPAPI (CurrentUser scope) wrapper for the opt-in "remember my password on this computer"
|
||
|
|
/// feature (SavedServer.ProtectedPasswordBase64). DPAPI keys are derived from the user's
|
||
|
|
/// Windows credentials and are not portable/exportable — a stolen servers.json file alone,
|
||
|
|
/// copied to another machine or read by another OS user, is not decryptable. This is the same
|
||
|
|
/// primitive Windows Credential Manager and many first-party Windows apps use for exactly this
|
||
|
|
/// "remember a secret only on this machine, only for this user" case.
|
||
|
|
/// </summary>
|
||
|
|
public static class PasswordProtector
|
||
|
|
{
|
||
|
|
public static string Protect(string plaintext)
|
||
|
|
{
|
||
|
|
byte[] data = Encoding.UTF8.GetBytes(plaintext);
|
||
|
|
byte[] protectedData = ProtectedData.Protect(data, optionalEntropy: null, DataProtectionScope.CurrentUser);
|
||
|
|
return Convert.ToBase64String(protectedData);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static string Unprotect(string protectedBase64)
|
||
|
|
{
|
||
|
|
byte[] protectedData = Convert.FromBase64String(protectedBase64);
|
||
|
|
byte[] data = ProtectedData.Unprotect(protectedData, optionalEntropy: null, DataProtectionScope.CurrentUser);
|
||
|
|
return Encoding.UTF8.GetString(data);
|
||
|
|
}
|
||
|
|
}
|