From 5320e8d9cc3205d8d37b804f8122b59122f19c7a Mon Sep 17 00:00:00 2001 From: Archi Date: Sat, 10 Feb 2024 18:03:32 +0100 Subject: [PATCH] Misc refactor after #3142 --- ArchiSteamFarm/Helpers/ArchiCryptoHelper.cs | 95 +++++++++++---------- 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/ArchiSteamFarm/Helpers/ArchiCryptoHelper.cs b/ArchiSteamFarm/Helpers/ArchiCryptoHelper.cs index 8aef5d0ab..cf2d09654 100644 --- a/ArchiSteamFarm/Helpers/ArchiCryptoHelper.cs +++ b/ArchiSteamFarm/Helpers/ArchiCryptoHelper.cs @@ -59,72 +59,57 @@ public static class ArchiCryptoHelper { private static byte[] EncryptionKey = Encoding.UTF8.GetBytes(nameof(ArchiSteamFarm)); - internal static async Task Decrypt(ECryptoMethod cryptoMethod, string encryptedString) { + internal static async Task Decrypt(ECryptoMethod cryptoMethod, string text) { if (!Enum.IsDefined(cryptoMethod)) { throw new InvalidEnumArgumentException(nameof(cryptoMethod), (int) cryptoMethod, typeof(ECryptoMethod)); } - ArgumentException.ThrowIfNullOrEmpty(encryptedString); + ArgumentException.ThrowIfNullOrEmpty(text); return cryptoMethod switch { - ECryptoMethod.AES => DecryptAES(encryptedString), - ECryptoMethod.EnvironmentVariable => Environment.GetEnvironmentVariable(encryptedString)?.Trim(), - ECryptoMethod.File => await ReadFromFile(encryptedString).ConfigureAwait(false), - ECryptoMethod.PlainText => encryptedString, - ECryptoMethod.ProtectedDataForCurrentUser => DecryptProtectedDataForCurrentUser(encryptedString), + ECryptoMethod.AES => DecryptAES(text), + ECryptoMethod.EnvironmentVariable => Environment.GetEnvironmentVariable(text)?.Trim(), + ECryptoMethod.File => await ReadFromFile(text).ConfigureAwait(false), + ECryptoMethod.PlainText => text, + ECryptoMethod.ProtectedDataForCurrentUser => DecryptProtectedDataForCurrentUser(text), _ => throw new InvalidOperationException(nameof(cryptoMethod)) }; } - internal static string? Encrypt(ECryptoMethod cryptoMethod, string decryptedString) { + internal static string? Encrypt(ECryptoMethod cryptoMethod, string text) { if (!Enum.IsDefined(cryptoMethod)) { throw new InvalidEnumArgumentException(nameof(cryptoMethod), (int) cryptoMethod, typeof(ECryptoMethod)); } - ArgumentException.ThrowIfNullOrEmpty(decryptedString); + ArgumentException.ThrowIfNullOrEmpty(text); return cryptoMethod switch { - ECryptoMethod.AES => EncryptAES(decryptedString), - ECryptoMethod.EnvironmentVariable => decryptedString, - ECryptoMethod.File => decryptedString, - ECryptoMethod.PlainText => decryptedString, - ECryptoMethod.ProtectedDataForCurrentUser => EncryptProtectedDataForCurrentUser(decryptedString), + ECryptoMethod.AES => EncryptAES(text), + ECryptoMethod.EnvironmentVariable => text, + ECryptoMethod.File => text, + ECryptoMethod.PlainText => text, + ECryptoMethod.ProtectedDataForCurrentUser => EncryptProtectedDataForCurrentUser(text), _ => throw new InvalidOperationException(nameof(cryptoMethod)) }; } - internal static string Hash(EHashingMethod hashingMethod, string stringToHash) { + internal static string Hash(EHashingMethod hashingMethod, string text) { if (!Enum.IsDefined(hashingMethod)) { throw new InvalidEnumArgumentException(nameof(hashingMethod), (int) hashingMethod, typeof(EHashingMethod)); } - ArgumentException.ThrowIfNullOrEmpty(stringToHash); + ArgumentException.ThrowIfNullOrEmpty(text); if (hashingMethod == EHashingMethod.PlainText) { - return stringToHash; + return text; } - byte[] passwordBytes = Encoding.UTF8.GetBytes(stringToHash); - byte[] hashBytes = Hash(passwordBytes, EncryptionKey, DefaultHashLength, hashingMethod); + byte[] textBytes = Encoding.UTF8.GetBytes(text); + byte[] hashBytes = Hash(textBytes, EncryptionKey, DefaultHashLength, hashingMethod); return Convert.ToBase64String(hashBytes); } - internal static bool VerifyHash(EHashingMethod hashingMethod, string inputString, string verifyHash) { - if (!Enum.IsDefined(hashingMethod)) { - throw new InvalidEnumArgumentException(nameof(hashingMethod), (int) hashingMethod, typeof(EHashingMethod)); - } - - ArgumentException.ThrowIfNullOrEmpty(inputString); - ArgumentException.ThrowIfNullOrEmpty(verifyHash); - - byte[] verifyBytes = hashingMethod == EHashingMethod.PlainText ? Encoding.UTF8.GetBytes(inputString) : Convert.FromBase64String(verifyHash); - byte[] passwordBytes = Encoding.UTF8.GetBytes(inputString); - byte[] hashBytes = Hash(passwordBytes, EncryptionKey, DefaultHashLength, hashingMethod); - - return CryptographicOperations.FixedTimeEquals(hashBytes, verifyBytes); - } - internal static byte[] Hash(byte[] password, byte[] salt, byte hashLength, EHashingMethod hashingMethod) { if ((password == null) || (password.Length == 0)) { throw new ArgumentNullException(nameof(password)); @@ -212,13 +197,31 @@ public static class ArchiCryptoHelper { EncryptionKey = encryptionKey; } - private static string? DecryptAES(string encryptedString) { - ArgumentException.ThrowIfNullOrEmpty(encryptedString); + internal static bool VerifyHash(EHashingMethod hashingMethod, string text, string hash) { + if (!Enum.IsDefined(hashingMethod)) { + throw new InvalidEnumArgumentException(nameof(hashingMethod), (int) hashingMethod, typeof(EHashingMethod)); + } + + ArgumentException.ThrowIfNullOrEmpty(text); + ArgumentException.ThrowIfNullOrEmpty(hash); + + // Text is always provided as plain text + byte[] textBytes = Encoding.UTF8.GetBytes(text); + textBytes = Hash(textBytes, EncryptionKey, DefaultHashLength, hashingMethod); + + // Hash is either plain text password (when EHashingMethod.PlainText), or base64-encoded hash + byte[] hashBytes = hashingMethod == EHashingMethod.PlainText ? Encoding.UTF8.GetBytes(hash) : Convert.FromBase64String(hash); + + return CryptographicOperations.FixedTimeEquals(textBytes, hashBytes); + } + + private static string? DecryptAES(string text) { + ArgumentException.ThrowIfNullOrEmpty(text); try { byte[] key = SHA256.HashData(EncryptionKey); - byte[] decryptedData = Convert.FromBase64String(encryptedString); + byte[] decryptedData = Convert.FromBase64String(text); decryptedData = CryptoHelper.SymmetricDecrypt(decryptedData, key); return Encoding.UTF8.GetString(decryptedData); @@ -229,8 +232,8 @@ public static class ArchiCryptoHelper { } } - private static string? DecryptProtectedDataForCurrentUser(string encryptedString) { - ArgumentException.ThrowIfNullOrEmpty(encryptedString); + private static string? DecryptProtectedDataForCurrentUser(string text) { + ArgumentException.ThrowIfNullOrEmpty(text); if (!OperatingSystem.IsWindows()) { return null; @@ -238,7 +241,7 @@ public static class ArchiCryptoHelper { try { byte[] decryptedData = ProtectedData.Unprotect( - Convert.FromBase64String(encryptedString), + Convert.FromBase64String(text), EncryptionKey, DataProtectionScope.CurrentUser ); @@ -251,13 +254,13 @@ public static class ArchiCryptoHelper { } } - private static string? EncryptAES(string decryptedString) { - ArgumentException.ThrowIfNullOrEmpty(decryptedString); + private static string? EncryptAES(string text) { + ArgumentException.ThrowIfNullOrEmpty(text); try { byte[] key = SHA256.HashData(EncryptionKey); - byte[] encryptedData = Encoding.UTF8.GetBytes(decryptedString); + byte[] encryptedData = Encoding.UTF8.GetBytes(text); encryptedData = CryptoHelper.SymmetricEncrypt(encryptedData, key); return Convert.ToBase64String(encryptedData); @@ -268,8 +271,8 @@ public static class ArchiCryptoHelper { } } - private static string? EncryptProtectedDataForCurrentUser(string decryptedString) { - ArgumentException.ThrowIfNullOrEmpty(decryptedString); + private static string? EncryptProtectedDataForCurrentUser(string text) { + ArgumentException.ThrowIfNullOrEmpty(text); if (!OperatingSystem.IsWindows()) { return null; @@ -277,7 +280,7 @@ public static class ArchiCryptoHelper { try { byte[] encryptedData = ProtectedData.Protect( - Encoding.UTF8.GetBytes(decryptedString), + Encoding.UTF8.GetBytes(text), EncryptionKey, DataProtectionScope.CurrentUser );