From 02c275a7d0194d91cf6472e6aadb8fc3a61364dd Mon Sep 17 00:00:00 2001 From: Carson McManus Date: Sun, 21 Aug 2016 17:02:17 -0400 Subject: [PATCH] Removed anything that had to do with encrypted maFiles because I can't reference System.Security.dll with mcs :( Will fix later. --- Program.cs | 323 ++++++++--------------------------------------------- makefile | 5 +- 2 files changed, 48 insertions(+), 280 deletions(-) diff --git a/Program.cs b/Program.cs index d728a7c..a77c494 100644 --- a/Program.cs +++ b/Program.cs @@ -12,6 +12,8 @@ public static class Program const string defaultSteamGuardPath = "~/maFiles"; public static string SteamGuardPath { get; set; } = defaultSteamGuardPath; + public static Manifest Manifest { get; set; } + public static SteamGuardAccount[] SteamGuardAccounts { get; set; } /// /// The main entry point for the application @@ -41,6 +43,10 @@ public static class Program return; } } + + // Load the manifest and stuff + Manifest = Manifest.GetManifest(); + SteamGuardAccounts = Manifest.GetAllAccounts(); } } @@ -86,7 +92,7 @@ public class Manifest } // Find config dir and manifest file - string maDir = Manifest.GetExecutableDir() + "/maFiles/"; + string maDir = Program.SteamGuardPath; string maFile = maDir + "manifest.json"; // If there's no config dir, create it @@ -139,7 +145,7 @@ public class Manifest // Take a pre-manifest version and generate a manifest for it. if (scanDir) { - string maDir = Manifest.GetExecutableDir() + "/maFiles/"; + string maDir = Program.SteamGuardPath + "/maFiles/"; if (Directory.Exists(maDir)) { DirectoryInfo dir = new DirectoryInfo(maDir); @@ -192,23 +198,17 @@ public class Manifest } bool passKeyValid = false; - string passKey = null; + string passKey = ""; while (!passKeyValid) { - InputForm passKeyForm = new InputForm("Please enter your encryption passkey.", true); - passKeyForm.ShowDialog(); - if (!passKeyForm.Canceled) + Console.WriteLine("Please enter encryption password: "); + passKey = Console.ReadLine(); + if (passKey == "") + continue; + passKeyValid = this.VerifyPasskey(passKey); + if (!passKeyValid) { - passKey = passKeyForm.txtBox.Text; - passKeyValid = this.VerifyPasskey(passKey); - if (!passKeyValid) - { - MessageBox.Show("That passkey is invalid."); - } - } - else - { - return null; + Console.WriteLine("Incorrect."); } } return passKey; @@ -216,39 +216,37 @@ public class Manifest public string PromptSetupPassKey(string initialPrompt = "Enter passkey, or hit cancel to remain unencrypted.") { - InputForm newPassKeyForm = new InputForm(initialPrompt); - newPassKeyForm.ShowDialog(); - if (newPassKeyForm.Canceled || newPassKeyForm.txtBox.Text.Length == 0) + Console.Write("Would you like to use encryption? [Y/n] "); + string doEncryptAnswer = Console.ReadLine(); + if (doEncryptAnswer == "n" || doEncryptAnswer == "N") { - MessageBox.Show("WARNING: You chose to not encrypt your files. Doing so imposes a security risk for yourself. If an attacker were to gain access to your computer, they could completely lock you out of your account and steal all your items."); + Console.WriteLine("WARNING: You chose to not encrypt your files. Doing so imposes a security risk for yourself. If an attacker were to gain access to your computer, they could completely lock you out of your account and steal all your items."); return null; } - InputForm newPassKeyForm2 = new InputForm("Confirm new passkey."); - newPassKeyForm2.ShowDialog(); - if (newPassKeyForm2.Canceled) + string newPassKey = ""; + string confirmPassKey = ""; + do { - MessageBox.Show("WARNING: You chose to not encrypt your files. Doing so imposes a security risk for yourself. If an attacker were to gain access to your computer, they could completely lock you out of your account and steal all your items."); - return null; - } + Console.Write("Enter passkey: "); + newPassKey = Console.ReadLine(); + Console.Write("Confirm passkey: "); + confirmPassKey = Console.ReadLine(); - string newPassKey = newPassKeyForm.txtBox.Text; - string confirmPassKey = newPassKeyForm2.txtBox.Text; - - if (newPassKey != confirmPassKey) - { - MessageBox.Show("Passkeys do not match."); - return null; - } + if (newPassKey != confirmPassKey) + { + Console.WriteLine("Passkeys do not match."); + } + } while (newPassKey != confirmPassKey); if (!this.ChangeEncryptionKey(null, newPassKey)) { - MessageBox.Show("Unable to set passkey."); + Console.WriteLine("Unable to set passkey."); return null; } else { - MessageBox.Show("Passkey successfully set."); + Console.WriteLine("Passkey successfully set."); } return newPassKey; @@ -257,7 +255,7 @@ public class Manifest public SteamAuth.SteamGuardAccount[] GetAllAccounts(string passKey = null, int limit = -1) { if (passKey == null && this.Encrypted) return new SteamGuardAccount[0]; - string maDir = Manifest.GetExecutableDir() + "/maFiles/"; + string maDir = Program.SteamGuardPath + "/maFiles/"; List accounts = new List(); foreach (var entry in this.Entries) @@ -265,9 +263,10 @@ public class Manifest string fileText = File.ReadAllText(maDir + entry.Filename); if (this.Encrypted) { - string decryptedText = FileEncryptor.DecryptData(passKey, entry.Salt, entry.IV, fileText); - if (decryptedText == null) return new SteamGuardAccount[0]; - fileText = decryptedText; + throw new NotSupportedException("Encrypted maFiles are not supported at this time."); + //string decryptedText = FileEncryptor.DecryptData(passKey, entry.Salt, entry.IV, fileText); + //if (decryptedText == null) return new SteamGuardAccount[0]; + //fileText = decryptedText; } var account = JsonConvert.DeserializeObject(fileText); @@ -283,48 +282,7 @@ public class Manifest public bool ChangeEncryptionKey(string oldKey, string newKey) { - if (this.Encrypted) - { - if (!this.VerifyPasskey(oldKey)) - { - return false; - } - } - bool toEncrypt = newKey != null; - - string maDir = Manifest.GetExecutableDir() + "/maFiles/"; - for (int i = 0; i < this.Entries.Count; i++) - { - ManifestEntry entry = this.Entries[i]; - string filename = maDir + entry.Filename; - if (!File.Exists(filename)) continue; - - string fileContents = File.ReadAllText(filename); - if (this.Encrypted) - { - fileContents = FileEncryptor.DecryptData(oldKey, entry.Salt, entry.IV, fileContents); - } - - string newSalt = null; - string newIV = null; - string toWriteFileContents = fileContents; - - if (toEncrypt) - { - newSalt = FileEncryptor.GetRandomSalt(); - newIV = FileEncryptor.GetInitializationVector(); - toWriteFileContents = FileEncryptor.EncryptData(newKey, newSalt, newIV, fileContents); - } - - File.WriteAllText(filename, toWriteFileContents); - entry.IV = newIV; - entry.Salt = newSalt; - } - - this.Encrypted = toEncrypt; - - this.Save(); - return true; + throw new NotSupportedException("Encrypted maFiles are not supported at this time."); } public bool VerifyPasskey(string passkey) @@ -340,7 +298,7 @@ public class Manifest ManifestEntry entry = (from e in this.Entries where e.SteamID == account.Session.SteamID select e).FirstOrDefault(); if (entry == null) return true; // If something never existed, did you do what they asked? - string maDir = Manifest.GetExecutableDir() + "/maFiles/"; + string maDir = Program.SteamGuardPath + "/maFiles/"; string filename = maDir + entry.Filename; this.Entries.Remove(entry); @@ -376,14 +334,10 @@ public class Manifest if (encrypt) { - salt = FileEncryptor.GetRandomSalt(); - iV = FileEncryptor.GetInitializationVector(); - string encrypted = FileEncryptor.EncryptData(passKey, salt, iV, jsonAccount); - if (encrypted == null) return false; - jsonAccount = encrypted; + throw new NotSupportedException("Encrypted maFiles are not supported at this time."); } - string maDir = Manifest.GetExecutableDir() + "/maFiles/"; + string maDir = Program.SteamGuardPath + "/maFiles/"; string filename = account.Session.SteamID.ToString() + ".maFile"; ManifestEntry newEntry = new ManifestEntry() @@ -432,7 +386,7 @@ public class Manifest public bool Save() { - string maDir = Manifest.GetExecutableDir() + "/maFiles/"; + string maDir = Program.SteamGuardPath + "/maFiles/"; string filename = maDir + "manifest.json"; if (!Directory.Exists(maDir)) { @@ -461,7 +415,7 @@ public class Manifest private void RecomputeExistingEntries() { List newEntries = new List(); - string maDir = Manifest.GetExecutableDir() + "/maFiles/"; + string maDir = Program.SteamGuardPath + "/maFiles/"; foreach (var entry in this.Entries) { @@ -504,190 +458,3 @@ public class Manifest public ulong SteamID { get; set; } } } - -/// -/// This class provides the controls that will encrypt and decrypt the *.maFile files -/// -/// Passwords entered will be passed into 100k rounds of PBKDF2 (RFC2898) with a cryptographically random salt. -/// The generated key will then be passed into AES-256 (RijndalManaged) which will encrypt the data -/// in cypher block chaining (CBC) mode, and then write both the PBKDF2 salt and encrypted data onto the disk. -/// -public static class FileEncryptor -{ - private const int PBKDF2_ITERATIONS = 50000; //Set to 50k to make program not unbearably slow. May increase in future. - private const int SALT_LENGTH = 8; - private const int KEY_SIZE_BYTES = 32; - private const int IV_LENGTH = 16; - - /// - /// Returns an 8-byte cryptographically random salt in base64 encoding - /// - /// - public static string GetRandomSalt() - { - byte[] salt = new byte[SALT_LENGTH]; - using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) - { - rng.GetBytes(salt); - } - return Convert.ToBase64String(salt); - } - - /// - /// Returns a 16-byte cryptographically random initialization vector (IV) in base64 encoding - /// - /// - public static string GetInitializationVector() - { - byte[] IV = new byte[IV_LENGTH]; - using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) - { - rng.GetBytes(IV); - } - return Convert.ToBase64String(IV); - } - - - /// - /// Generates an encryption key derived using a password, a random salt, and specified number of rounds of PBKDF2 - /// - /// TODO: pass in password via SecureString? - /// - /// - /// - /// - private static byte[] GetEncryptionKey(string password, string salt) - { - if (string.IsNullOrEmpty(password)) - { - throw new ArgumentException("Password is empty"); - } - if (string.IsNullOrEmpty(salt)) - { - throw new ArgumentException("Salt is empty"); - } - using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, Convert.FromBase64String(salt), PBKDF2_ITERATIONS)) - { - return pbkdf2.GetBytes(KEY_SIZE_BYTES); - } - } - - /// - /// Tries to decrypt and return data given an encrypted base64 encoded string. Must use the same - /// password, salt, IV, and ciphertext that was used during the original encryption of the data. - /// - /// - /// - /// Initialization Vector - /// - /// - public static string DecryptData(string password, string passwordSalt, string IV, string encryptedData) - { - if (string.IsNullOrEmpty(password)) - { - throw new ArgumentException("Password is empty"); - } - if (string.IsNullOrEmpty(passwordSalt)) - { - throw new ArgumentException("Salt is empty"); - } - if (string.IsNullOrEmpty(IV)) - { - throw new ArgumentException("Initialization Vector is empty"); - } - if (string.IsNullOrEmpty(encryptedData)) - { - throw new ArgumentException("Encrypted data is empty"); - } - - byte[] cipherText = Convert.FromBase64String(encryptedData); - byte[] key = GetEncryptionKey(password, passwordSalt); - string plaintext = null; - - using (RijndaelManaged aes256 = new RijndaelManaged()) - { - aes256.IV = Convert.FromBase64String(IV); - aes256.Key = key; - aes256.Padding = PaddingMode.PKCS7; - aes256.Mode = CipherMode.CBC; - - //create decryptor to perform the stream transform - ICryptoTransform decryptor = aes256.CreateDecryptor(aes256.Key, aes256.IV); - - //wrap in a try since a bad password yields a bad key, which would throw an exception on decrypt - try - { - using (MemoryStream msDecrypt = new MemoryStream(cipherText)) - { - using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) - { - using (StreamReader srDecrypt = new StreamReader(csDecrypt)) - { - plaintext = srDecrypt.ReadToEnd(); - } - } - } - } - catch (CryptographicException) - { - plaintext = null; - } - } - return plaintext; - } - - /// - /// Encrypts a string given a password, salt, and initialization vector, then returns result in base64 encoded string. - /// - /// To retrieve this data, you must decrypt with the same password, salt, IV, and cyphertext that was used during encryption - /// - /// - /// - /// - /// - /// - public static string EncryptData(string password, string passwordSalt, string IV, string plaintext) - { - if (string.IsNullOrEmpty(password)) - { - throw new ArgumentException("Password is empty"); - } - if (string.IsNullOrEmpty(passwordSalt)) - { - throw new ArgumentException("Salt is empty"); - } - if (string.IsNullOrEmpty(IV)) - { - throw new ArgumentException("Initialization Vector is empty"); - } - if (string.IsNullOrEmpty(plaintext)) - { - throw new ArgumentException("Plaintext data is empty"); - } - byte[] key = GetEncryptionKey(password, passwordSalt); - byte[] ciphertext; - - using (RijndaelManaged aes256 = new RijndaelManaged()) - { - aes256.Key = key; - aes256.IV = Convert.FromBase64String(IV); - aes256.Padding = PaddingMode.PKCS7; - aes256.Mode = CipherMode.CBC; - - ICryptoTransform encryptor = aes256.CreateEncryptor(aes256.Key, aes256.IV); - - using (MemoryStream msEncrypt = new MemoryStream()) - { - using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) - { - using (StreamWriter swEncypt = new StreamWriter(csEncrypt)) - { - swEncypt.Write(plaintext); - } - ciphertext = msEncrypt.ToArray(); - } - } - } - return Convert.ToBase64String(ciphertext); - } -} diff --git a/makefile b/makefile index 74f7cbe..b76cce2 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,5 @@ all: Program.cs nuget restore SteamAuth/SteamAuth/SteamAuth.sln - mcs -target:library -out:build/libSteamAuth.so -r:SteamAuth/SteamAuth/packages/Newtonsoft.Json.7.0.1/lib/net45/Newtonsoft.Json.dll SteamAuth/SteamAuth/APIEndpoints.cs SteamAuth/SteamAuth/AuthenticatorLinker.cs SteamAuth/SteamAuth/Confirmation.cs SteamAuth/SteamAuth/SessionData.cs SteamAuth/SteamAuth/SteamGuardAccount.cs SteamAuth/SteamAuth/SteamWeb.cs SteamAuth/SteamAuth/TimeAligner.cs SteamAuth/SteamAuth/UserLogin.cs SteamAuth/SteamAuth/Util.cs SteamAuth/SteamAuth/Properties/AssemblyInfo.cs - mcs -out:build/steamguard -r:build/libSteamAuth.so -r:SteamAuth/SteamAuth/packages/Newtonsoft.Json.7.0.1/lib/net45/Newtonsoft.Json.dll Program.cs + mcs -target:library -out:build/SteamAuth.dll -r:SteamAuth/SteamAuth/packages/Newtonsoft.Json.7.0.1/lib/net45/Newtonsoft.Json.dll SteamAuth/SteamAuth/APIEndpoints.cs SteamAuth/SteamAuth/AuthenticatorLinker.cs SteamAuth/SteamAuth/Confirmation.cs SteamAuth/SteamAuth/SessionData.cs SteamAuth/SteamAuth/SteamGuardAccount.cs SteamAuth/SteamAuth/SteamWeb.cs SteamAuth/SteamAuth/TimeAligner.cs SteamAuth/SteamAuth/UserLogin.cs SteamAuth/SteamAuth/Util.cs SteamAuth/SteamAuth/Properties/AssemblyInfo.cs + cp SteamAuth/SteamAuth/packages/Newtonsoft.Json.7.0.1/lib/net45/Newtonsoft.Json.dll build/ + mcs -out:build/steamguard -r:build/SteamAuth.dll -r:build/Newtonsoft.Json.dll Program.cs