├── icon.png ├── .gitmodules ├── Steam Desktop Authenticator ├── icon.ico ├── ManifestParseException.cs ├── MaFileEncryptedException.cs ├── App.config ├── packages.config ├── DeleteAllCookiesVisitor.cs ├── ResourceResponseFilter.cs ├── CommandLineOptions.cs ├── ListInputForm.cs ├── CaptchaForm.cs ├── Steam Desktop Authenticator.sln ├── Properties │ └── AssemblyInfo.cs ├── InputForm.cs ├── SettingsForm.cs ├── InstallRedistribForm.cs ├── TradePopupForm.cs ├── InstallRedistribForm.Designer.cs ├── ListInputForm.Designer.cs ├── Program.cs ├── ConfirmationFormWeb.Designer.cs ├── WelcomeForm.cs ├── ConfirmationFormWeb.cs ├── InputForm.Designer.cs ├── BrowserRequestHandler.cs ├── ImportAccountForm.Designer.cs ├── WelcomeForm.Designer.cs ├── CaptchaForm.Designer.cs ├── TradePopupForm.Designer.cs ├── LoginForm.Designer.cs ├── SettingsForm.Designer.cs ├── FileEncryptor.cs ├── ImportAccountForm.cs ├── Steam Desktop Authenticator.csproj ├── PhoneBridge.cs ├── LoginForm.cs └── Manifest.cs ├── .gitattributes ├── LICENSE ├── prepare-release.bat ├── README.md └── .gitignore /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rudokhvist/SteamDesktopAuthenticator/HEAD/icon.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/SteamAuth"] 2 | path = lib/SteamAuth 3 | url = git://github.com/geel9/SteamAuth 4 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rudokhvist/SteamDesktopAuthenticator/HEAD/Steam Desktop Authenticator/icon.ico -------------------------------------------------------------------------------- /Steam Desktop Authenticator/ManifestParseException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Steam_Desktop_Authenticator 8 | { 9 | class ManifestParseException : Exception 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/MaFileEncryptedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Steam_Desktop_Authenticator 8 | { 9 | class MaFileEncryptedException : Exception 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain -------------------------------------------------------------------------------- /Steam Desktop Authenticator/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/DeleteAllCookiesVisitor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using CefSharp; 7 | 8 | namespace Steam_Desktop_Authenticator 9 | { 10 | public class DeleteAllCookiesVisitor : ICookieVisitor 11 | { 12 | public void Dispose() 13 | { 14 | 15 | } 16 | 17 | public bool Visit(Cookie cookie, int count, int total, ref bool deleteCookie) 18 | { 19 | deleteCookie = true; 20 | return true; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/ResourceResponseFilter.cs: -------------------------------------------------------------------------------- 1 | using CefSharp; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.IO; 8 | 9 | namespace Steam_Desktop_Authenticator 10 | { 11 | class ResourceResponseFilter : IResponseFilter 12 | { 13 | public void Dispose() 14 | { 15 | 16 | } 17 | 18 | public FilterStatus Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten) 19 | { 20 | dataInRead = 0; 21 | dataOutWritten = 0; 22 | return FilterStatus.Error; 23 | } 24 | 25 | public bool InitFilter() 26 | { 27 | return false; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/CommandLineOptions.cs: -------------------------------------------------------------------------------- 1 | using CommandLine; 2 | using CommandLine.Text; 3 | 4 | namespace Steam_Desktop_Authenticator 5 | { 6 | class CommandLineOptions 7 | { 8 | [Option('k', "encryption-key", Required = false, 9 | HelpText = "Encryption key for manifest")] 10 | public string EncryptionKey { get; set; } 11 | 12 | [Option('s', "silent", Required = false, 13 | HelpText = "Start minimized")] 14 | public bool Silent { get; set; } 15 | 16 | [ParserState] 17 | public IParserState LastParserState { get; set; } 18 | 19 | [HelpOption] 20 | public string GetUsage() 21 | { 22 | return HelpText.AutoBuild(this, 23 | (HelpText current) => HelpText.DefaultParsingErrorsHandler(this, current)); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jesse Cardone 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/ListInputForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace Steam_Desktop_Authenticator 12 | { 13 | public partial class ListInputForm : Form 14 | { 15 | public ListInputForm(List options) 16 | { 17 | Items = options; 18 | InitializeComponent(); 19 | } 20 | 21 | public int SelectedIndex; 22 | List Items; 23 | 24 | private void ListInputForm_Load(object sender, EventArgs e) 25 | { 26 | foreach (var item in Items) 27 | { 28 | lbItems.Items.Add(item); 29 | } 30 | } 31 | 32 | private void btnAccept_Click(object sender, EventArgs e) 33 | { 34 | if (lbItems.SelectedIndex != -1) 35 | { 36 | SelectedIndex = lbItems.SelectedIndex; 37 | this.Close(); 38 | } 39 | } 40 | 41 | private void btnCancel_Click(object sender, EventArgs e) 42 | { 43 | this.Close(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/CaptchaForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace Steam_Desktop_Authenticator 12 | { 13 | public partial class CaptchaForm : Form 14 | { 15 | public bool Canceled = false; 16 | public string CaptchaGID = ""; 17 | public string CaptchaURL = ""; 18 | public string CaptchaCode 19 | { 20 | get 21 | { 22 | return this.txtBox.Text; 23 | } 24 | } 25 | 26 | public CaptchaForm(string GID) 27 | { 28 | this.CaptchaGID = GID; 29 | this.CaptchaURL = "https://steamcommunity.com/public/captcha.php?gid=" + GID; 30 | InitializeComponent(); 31 | this.pictureBoxCaptcha.Load(CaptchaURL); 32 | } 33 | 34 | private void btnAccept_Click(object sender, EventArgs e) 35 | { 36 | this.Canceled = false; 37 | this.Close(); 38 | } 39 | 40 | private void btnCancel_Click(object sender, EventArgs e) 41 | { 42 | this.Canceled = true; 43 | this.Close(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/Steam Desktop Authenticator.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Steam Desktop Authenticator", "Steam Desktop Authenticator.csproj", "{0F37C513-9AF4-42C8-9CE9-F9B3BFA55E4E}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SteamAuth", "..\lib\SteamAuth\SteamAuth\SteamAuth.csproj", "{5AD0934E-F6C4-4AE5-83AF-C788313B2A87}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x86 = Debug|x86 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {0F37C513-9AF4-42C8-9CE9-F9B3BFA55E4E}.Debug|x86.ActiveCfg = Debug|x86 17 | {0F37C513-9AF4-42C8-9CE9-F9B3BFA55E4E}.Debug|x86.Build.0 = Debug|x86 18 | {0F37C513-9AF4-42C8-9CE9-F9B3BFA55E4E}.Release|x86.ActiveCfg = Release|x86 19 | {0F37C513-9AF4-42C8-9CE9-F9B3BFA55E4E}.Release|x86.Build.0 = Release|x86 20 | {5AD0934E-F6C4-4AE5-83AF-C788313B2A87}.Debug|x86.ActiveCfg = Debug|Any CPU 21 | {5AD0934E-F6C4-4AE5-83AF-C788313B2A87}.Debug|x86.Build.0 = Debug|Any CPU 22 | {5AD0934E-F6C4-4AE5-83AF-C788313B2A87}.Release|x86.ActiveCfg = Release|Any CPU 23 | {5AD0934E-F6C4-4AE5-83AF-C788313B2A87}.Release|x86.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /prepare-release.bat: -------------------------------------------------------------------------------- 1 | REM Remove un-needed CEF files 2 | del /q "Steam Desktop Authenticator\bin\Release\devtools_resources.pak" 3 | del /q "Steam Desktop Authenticator\bin\Release\cef_extensions.pak" 4 | del /q "Steam Desktop Authenticator\bin\Release\pdf.dll" 5 | del /q "Steam Desktop Authenticator\bin\Release\ffmpegsumo.dll" 6 | del /q "Steam Desktop Authenticator\bin\Release\d3dcompiler_43.dll" 7 | del /q "Steam Desktop Authenticator\bin\Release\widevinecdmadapter.dll" 8 | 9 | REM Remove CEF directories 10 | RD /S /Q "Steam Desktop Authenticator\bin\Release\locales\" 11 | RD /S /Q "Steam Desktop Authenticator\bin\Release\swiftshader\" 12 | 13 | REM Remove CEF debug files 14 | del /q "Steam Desktop Authenticator\bin\Release\CefSharp.BrowserSubprocess.Core.pdb" 15 | del /q "Steam Desktop Authenticator\bin\Release\CefSharp.BrowserSubprocess.pdb" 16 | del /q "Steam Desktop Authenticator\bin\Release\CefSharp.Core.pdb" 17 | del /q "Steam Desktop Authenticator\bin\Release\CefSharp.pdb" 18 | del /q "Steam Desktop Authenticator\bin\Release\CefSharp.WinForms.pdb" 19 | 20 | REM Remove XML files 21 | del /q "Steam Desktop Authenticator\bin\Release\Newtonsoft.Json.xml" 22 | del /q "Steam Desktop Authenticator\bin\Release\CefSharp.xml" 23 | del /q "Steam Desktop Authenticator\bin\Release\CefSharp.WinForms.xml" 24 | del /q "Steam Desktop Authenticator\bin\Release\CefSharp.Core.xml" 25 | del /q "Steam Desktop Authenticator\bin\Release\CommandLine.xml" 26 | 27 | REM Remove ClickOnce app 28 | del /q "Steam Desktop Authenticator\bin\Release\Steam Desktop Authenticator.application" 29 | RD /S /Q "Steam Desktop Authenticator\bin\Release\app.publish\" -------------------------------------------------------------------------------- /Steam Desktop Authenticator/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Steam Desktop Authenticator")] 9 | [assembly: AssemblyDescription("Desktop implementation of Steam's mobile authenticator app")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Steam Desktop Authenticator")] 13 | [assembly: AssemblyCopyright("Copyright 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(true)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("0f37c513-9af4-42c8-9ce9-f9b3bfa55e4e")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.10")] 36 | [assembly: AssemblyFileVersion("1.0.10")] 37 | 38 | [assembly: AssemblyMetadata("SquirrelAwareVersion", "1")] -------------------------------------------------------------------------------- /Steam Desktop Authenticator/InputForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace Steam_Desktop_Authenticator 12 | { 13 | public partial class InputForm : Form 14 | { 15 | public bool Canceled = false; 16 | private bool userClosed = true; 17 | 18 | public InputForm(string label, bool password = false) 19 | { 20 | InitializeComponent(); 21 | this.labelText.Text = label; 22 | 23 | if (password) 24 | { 25 | this.txtBox.PasswordChar = '*'; 26 | } 27 | } 28 | 29 | private void btnAccept_Click(object sender, EventArgs e) 30 | { 31 | if (string.IsNullOrEmpty(this.txtBox.Text)) 32 | { 33 | this.Canceled = true; 34 | this.userClosed = false; 35 | this.Close(); 36 | } 37 | else 38 | { 39 | this.Canceled = false; 40 | this.userClosed = false; 41 | this.Close(); 42 | } 43 | } 44 | 45 | private void btnCancel_Click(object sender, EventArgs e) 46 | { 47 | this.Canceled = true; 48 | this.userClosed = false; 49 | this.Close(); 50 | } 51 | 52 | private void InputForm_FormClosing(object sender, FormClosingEventArgs e) 53 | { 54 | if (this.userClosed) 55 | { 56 | // Set Canceled = true when the user hits the X button. 57 | this.Canceled = true; 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/SettingsForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace Steam_Desktop_Authenticator 5 | { 6 | public partial class SettingsForm : Form 7 | { 8 | Manifest manifest; 9 | bool fullyLoaded = false; 10 | 11 | public SettingsForm() 12 | { 13 | InitializeComponent(); 14 | 15 | // Get latest manifest 16 | manifest = Manifest.GetManifest(true); 17 | 18 | chkPeriodicChecking.Checked = manifest.PeriodicChecking; 19 | numPeriodicInterval.Value = manifest.PeriodicCheckingInterval; 20 | chkCheckAll.Checked = manifest.CheckAllAccounts; 21 | chkConfirmMarket.Checked = manifest.AutoConfirmMarketTransactions; 22 | chkConfirmTrades.Checked = manifest.AutoConfirmTrades; 23 | 24 | SetControlsEnabledState(chkPeriodicChecking.Checked); 25 | 26 | fullyLoaded = true; 27 | } 28 | 29 | private void SetControlsEnabledState(bool enabled) 30 | { 31 | numPeriodicInterval.Enabled = chkCheckAll.Enabled = chkConfirmMarket.Enabled = chkConfirmTrades.Enabled = enabled; 32 | } 33 | 34 | private void ShowWarning(CheckBox affectedBox) 35 | { 36 | if (!fullyLoaded) return; 37 | 38 | var result = MessageBox.Show("Warning: enabling this will severely reduce the security of your items! Use of this option is at your own risk. Would you like to continue?", "Warning!", MessageBoxButtons.YesNo); 39 | if (result == DialogResult.No) 40 | { 41 | affectedBox.Checked = false; 42 | } 43 | } 44 | 45 | private void btnSave_Click(object sender, EventArgs e) 46 | { 47 | manifest.PeriodicChecking = chkPeriodicChecking.Checked; 48 | manifest.PeriodicCheckingInterval = (int)numPeriodicInterval.Value; 49 | manifest.CheckAllAccounts = chkCheckAll.Checked; 50 | manifest.AutoConfirmMarketTransactions = chkConfirmMarket.Checked; 51 | manifest.AutoConfirmTrades = chkConfirmTrades.Checked; 52 | manifest.Save(); 53 | this.Close(); 54 | } 55 | 56 | private void chkPeriodicChecking_CheckedChanged(object sender, EventArgs e) 57 | { 58 | SetControlsEnabledState(chkPeriodicChecking.Checked); 59 | } 60 | 61 | private void chkConfirmMarket_CheckedChanged(object sender, EventArgs e) 62 | { 63 | if (chkConfirmMarket.Checked) 64 | ShowWarning(chkConfirmMarket); 65 | } 66 | 67 | private void chkConfirmTrades_CheckedChanged(object sender, EventArgs e) 68 | { 69 | if (chkConfirmTrades.Checked) 70 | ShowWarning(chkConfirmTrades); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/InstallRedistribForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using System.Net; 11 | using System.Diagnostics; 12 | 13 | namespace Steam_Desktop_Authenticator 14 | { 15 | public partial class InstallRedistribForm : Form 16 | { 17 | private bool inlineInstall = false; 18 | 19 | public InstallRedistribForm(bool inlineInstall = false) 20 | { 21 | InitializeComponent(); 22 | progressBar1.Minimum = 0; 23 | 24 | string path = Manifest.GetExecutableDir() + "/vcredist_x86.exe"; 25 | 26 | WebClient client = new WebClient(); 27 | client.DownloadFileAsync(new Uri("https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x86.exe"), path); 28 | client.DownloadProgressChanged += Client_DownloadProgressChanged; 29 | client.DownloadFileCompleted += Client_DownloadFileCompleted; 30 | } 31 | 32 | private void Client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) 33 | { 34 | progressBar1.Style = ProgressBarStyle.Marquee; 35 | try 36 | { 37 | ProcessStartInfo startInfo = new ProcessStartInfo(); 38 | startInfo.FileName = Manifest.GetExecutableDir() + "/vcredist_x86.exe"; 39 | startInfo.Verb = "runas"; 40 | startInfo.Arguments = "/q"; 41 | startInfo.WindowStyle = ProcessWindowStyle.Normal; 42 | 43 | Process installProcess = new Process(); 44 | installProcess.StartInfo = startInfo; 45 | installProcess.EnableRaisingEvents = true; 46 | installProcess.Exited += InstallProcess_Exited; 47 | installProcess.Start(); 48 | } 49 | catch (Exception) 50 | { 51 | this.Close(); 52 | } 53 | } 54 | 55 | private void InstallProcess_Exited(object sender, EventArgs e) 56 | { 57 | if (inlineInstall) 58 | { 59 | MessageBox.Show("Install complete! You may need to restart Steam Desktop Authenticator to view trade confirmations.", "Visual C++ Redistributable 2013", MessageBoxButtons.OK, MessageBoxIcon.Information); 60 | } 61 | 62 | this.Invoke((MethodInvoker)delegate 63 | { 64 | this.Close(); 65 | }); 66 | } 67 | 68 | private void Client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) 69 | { 70 | progressBar1.Maximum = (int)e.TotalBytesToReceive; 71 | progressBar1.Value = (int)e.BytesReceived; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/TradePopupForm.cs: -------------------------------------------------------------------------------- 1 | using SteamAuth; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Data; 6 | using System.Drawing; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace Steam_Desktop_Authenticator 13 | { 14 | public partial class TradePopupForm : Form 15 | { 16 | private SteamGuardAccount acc; 17 | private List confirms = new List(); 18 | private bool deny2, accept2; 19 | 20 | public TradePopupForm() 21 | { 22 | InitializeComponent(); 23 | lblStatus.Text = ""; 24 | } 25 | 26 | public SteamGuardAccount Account 27 | { 28 | get { return acc; } 29 | set { acc = value; lblAccount.Text = acc.AccountName; } 30 | } 31 | 32 | public Confirmation[] Confirmations 33 | { 34 | get { return confirms.ToArray(); } 35 | set { confirms = new List(value); } 36 | } 37 | 38 | private void TradePopupForm_Load(object sender, EventArgs e) 39 | { 40 | this.Location = (Point)Size.Subtract(Screen.GetWorkingArea(this).Size, this.Size); 41 | } 42 | 43 | private void btnAccept_Click(object sender, EventArgs e) 44 | { 45 | if (!accept2) 46 | { 47 | // Allow user to confirm first 48 | lblStatus.Text = "Press Accept again to confirm"; 49 | btnAccept.BackColor = Color.FromArgb(128, 255, 128); 50 | accept2 = true; 51 | } 52 | else 53 | { 54 | lblStatus.Text = "Accepting..."; 55 | acc.AcceptConfirmation(confirms[0]); 56 | confirms.RemoveAt(0); 57 | Reset(); 58 | } 59 | } 60 | 61 | private void btnDeny_Click(object sender, EventArgs e) 62 | { 63 | if (!deny2) 64 | { 65 | lblStatus.Text = "Press Deny again to confirm"; 66 | btnDeny.BackColor = Color.FromArgb(255, 255, 128); 67 | deny2 = true; 68 | } 69 | else 70 | { 71 | lblStatus.Text = "Denying..."; 72 | acc.DenyConfirmation(confirms[0]); 73 | confirms.RemoveAt(0); 74 | Reset(); 75 | } 76 | } 77 | 78 | private void Reset() 79 | { 80 | deny2 = false; 81 | accept2 = false; 82 | btnAccept.BackColor = Color.FromArgb(192, 255, 192); 83 | btnDeny.BackColor = Color.FromArgb(255, 255, 192); 84 | 85 | btnAccept.Text = "Accept"; 86 | btnDeny.Text = "Deny"; 87 | lblAccount.Text = ""; 88 | lblStatus.Text = ""; 89 | 90 | if (confirms.Count == 0) 91 | { 92 | this.Hide(); 93 | } 94 | else 95 | { 96 | //TODO: Re-add confirmation description support to SteamAuth. 97 | lblDesc.Text = "Confirmation"; 98 | } 99 | } 100 | 101 | public void Popup() 102 | { 103 | Reset(); 104 | this.Show(); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/InstallRedistribForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Steam_Desktop_Authenticator 2 | { 3 | partial class InstallRedistribForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InstallRedistribForm)); 32 | this.label1 = new System.Windows.Forms.Label(); 33 | this.progressBar1 = new System.Windows.Forms.ProgressBar(); 34 | this.SuspendLayout(); 35 | // 36 | // label1 37 | // 38 | this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 39 | this.label1.Location = new System.Drawing.Point(12, 9); 40 | this.label1.Name = "label1"; 41 | this.label1.Size = new System.Drawing.Size(289, 45); 42 | this.label1.TabIndex = 0; 43 | this.label1.Text = "Installing Visual C++ Redistributable 2013..."; 44 | this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 45 | // 46 | // progressBar1 47 | // 48 | this.progressBar1.Location = new System.Drawing.Point(12, 57); 49 | this.progressBar1.Name = "progressBar1"; 50 | this.progressBar1.Size = new System.Drawing.Size(289, 28); 51 | this.progressBar1.TabIndex = 1; 52 | // 53 | // InstallRedistribForm 54 | // 55 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 56 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 57 | this.ClientSize = new System.Drawing.Size(313, 97); 58 | this.Controls.Add(this.progressBar1); 59 | this.Controls.Add(this.label1); 60 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 61 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 62 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 63 | this.MaximizeBox = false; 64 | this.Name = "InstallRedistribForm"; 65 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 66 | this.Text = "Installing"; 67 | this.ResumeLayout(false); 68 | 69 | } 70 | 71 | #endregion 72 | 73 | private System.Windows.Forms.Label label1; 74 | private System.Windows.Forms.ProgressBar progressBar1; 75 | } 76 | } -------------------------------------------------------------------------------- /Steam Desktop Authenticator/ListInputForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Steam_Desktop_Authenticator 2 | { 3 | partial class ListInputForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ListInputForm)); 32 | this.lbItems = new System.Windows.Forms.ListBox(); 33 | this.btnAccept = new System.Windows.Forms.Button(); 34 | this.btnCancel = new System.Windows.Forms.Button(); 35 | this.SuspendLayout(); 36 | // 37 | // lbItems 38 | // 39 | this.lbItems.FormattingEnabled = true; 40 | this.lbItems.Location = new System.Drawing.Point(23, 63); 41 | this.lbItems.Name = "lbItems"; 42 | this.lbItems.Size = new System.Drawing.Size(248, 82); 43 | this.lbItems.TabIndex = 0; 44 | // 45 | // btnAccept 46 | // 47 | this.btnAccept.Location = new System.Drawing.Point(277, 63); 48 | this.btnAccept.Name = "btnAccept"; 49 | this.btnAccept.Size = new System.Drawing.Size(75, 23); 50 | this.btnAccept.TabIndex = 1; 51 | this.btnAccept.Text = "Accept"; 52 | this.btnAccept.UseVisualStyleBackColor = true; 53 | this.btnAccept.Click += new System.EventHandler(this.btnAccept_Click); 54 | // 55 | // btnCancel 56 | // 57 | this.btnCancel.Location = new System.Drawing.Point(277, 122); 58 | this.btnCancel.Name = "btnCancel"; 59 | this.btnCancel.Size = new System.Drawing.Size(75, 23); 60 | this.btnCancel.TabIndex = 2; 61 | this.btnCancel.Text = "Cancel"; 62 | this.btnCancel.UseVisualStyleBackColor = true; 63 | this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); 64 | // 65 | // ListInputForm 66 | // 67 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 68 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 69 | this.ClientSize = new System.Drawing.Size(372, 172); 70 | this.Controls.Add(this.btnCancel); 71 | this.Controls.Add(this.btnAccept); 72 | this.Controls.Add(this.lbItems); 73 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 74 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 75 | this.Name = "ListInputForm"; 76 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 77 | this.Text = "Select one"; 78 | this.Load += new System.EventHandler(this.ListInputForm_Load); 79 | this.ResumeLayout(false); 80 | 81 | } 82 | 83 | #endregion 84 | 85 | private System.Windows.Forms.ListBox lbItems; 86 | private System.Windows.Forms.Button btnAccept; 87 | private System.Windows.Forms.Button btnCancel; 88 | } 89 | } -------------------------------------------------------------------------------- /Steam Desktop Authenticator/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using System.Diagnostics; 4 | using CommandLine; 5 | 6 | namespace Steam_Desktop_Authenticator 7 | { 8 | static class Program 9 | { 10 | public static Process PriorProcess() 11 | // Returns a System.Diagnostics.Process pointing to 12 | // a pre-existing process with the same name as the 13 | // current one, if any; or null if the current process 14 | // is unique. 15 | { 16 | try 17 | { 18 | Process curr = Process.GetCurrentProcess(); 19 | Process[] procs = Process.GetProcessesByName(curr.ProcessName); 20 | foreach (Process p in procs) 21 | { 22 | if ((p.Id != curr.Id) && 23 | (p.MainModule.FileName == curr.MainModule.FileName)) 24 | return p; 25 | } 26 | return null; 27 | } 28 | catch (Exception) 29 | { 30 | return null; 31 | } 32 | } 33 | 34 | /// 35 | /// The main entry point for the application. 36 | /// 37 | [STAThread] 38 | static void Main(string[] args) 39 | { 40 | // run the program only once 41 | if (PriorProcess() != null) 42 | { 43 | MessageBox.Show("Another instance of the app is already running."); 44 | return; 45 | } 46 | 47 | // Parse command line arguments 48 | var options = new CommandLineOptions(); 49 | Parser.Default.ParseArguments(args, options); 50 | 51 | Application.EnableVisualStyles(); 52 | Application.SetCompatibleTextRenderingDefault(false); 53 | 54 | Manifest man; 55 | 56 | try 57 | { 58 | man = Manifest.GetManifest(); 59 | } 60 | catch (ManifestParseException) 61 | { 62 | // Manifest file was corrupted, generate a new one. 63 | try 64 | { 65 | MessageBox.Show("Your settings were unexpectedly corrupted and were reset to defaults.", "Steam Desktop Authenticator", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); 66 | man = Manifest.GenerateNewManifest(true); 67 | } 68 | catch (MaFileEncryptedException) 69 | { 70 | // An maFile was encrypted, we're fucked. 71 | MessageBox.Show("Sorry, but SDA was unable to recover your accounts since you used encryption.\nYou'll need to recover your Steam accounts by removing the authenticator.\nClick OK to view instructions.", "Steam Desktop Authenticator", MessageBoxButtons.OK, MessageBoxIcon.Error); 72 | System.Diagnostics.Process.Start(@"https://github.com/Jessecar96/SteamDesktopAuthenticator/wiki/Help!-I'm-locked-out-of-my-account"); 73 | return; 74 | } 75 | } 76 | 77 | if (man.FirstRun) 78 | { 79 | // Install VC++ Redist and wait 80 | new InstallRedistribForm().ShowDialog(); 81 | 82 | if (man.Entries.Count > 0) 83 | { 84 | // Already has accounts, just run 85 | MainForm mf = new MainForm(); 86 | mf.SetEncryptionKey(options.EncryptionKey); 87 | mf.StartSilent(options.Silent); 88 | Application.Run(mf); 89 | } 90 | else 91 | { 92 | // No accounts, run welcome form 93 | Application.Run(new WelcomeForm()); 94 | } 95 | } 96 | else 97 | { 98 | MainForm mf = new MainForm(); 99 | mf.SetEncryptionKey(options.EncryptionKey); 100 | mf.StartSilent(options.Silent); 101 | Application.Run(mf); 102 | } 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/ConfirmationFormWeb.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Steam_Desktop_Authenticator 2 | { 3 | partial class ConfirmationFormWeb 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ConfirmationFormWeb)); 32 | this.splitContainer1 = new System.Windows.Forms.SplitContainer(); 33 | this.btnRefresh = new System.Windows.Forms.Button(); 34 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); 35 | this.splitContainer1.Panel1.SuspendLayout(); 36 | this.splitContainer1.SuspendLayout(); 37 | this.SuspendLayout(); 38 | // 39 | // splitContainer1 40 | // 41 | this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; 42 | this.splitContainer1.IsSplitterFixed = true; 43 | this.splitContainer1.Location = new System.Drawing.Point(0, 0); 44 | this.splitContainer1.Name = "splitContainer1"; 45 | this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; 46 | // 47 | // splitContainer1.Panel1 48 | // 49 | this.splitContainer1.Panel1.Controls.Add(this.btnRefresh); 50 | this.splitContainer1.Size = new System.Drawing.Size(431, 641); 51 | this.splitContainer1.SplitterDistance = 30; 52 | this.splitContainer1.SplitterWidth = 1; 53 | this.splitContainer1.TabIndex = 0; 54 | // 55 | // btnRefresh 56 | // 57 | this.btnRefresh.Dock = System.Windows.Forms.DockStyle.Fill; 58 | this.btnRefresh.Location = new System.Drawing.Point(0, 0); 59 | this.btnRefresh.Name = "btnRefresh"; 60 | this.btnRefresh.Size = new System.Drawing.Size(431, 30); 61 | this.btnRefresh.TabIndex = 0; 62 | this.btnRefresh.Text = "Refresh"; 63 | this.btnRefresh.UseVisualStyleBackColor = true; 64 | this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click); 65 | // 66 | // ConfirmationFormWeb 67 | // 68 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 69 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 70 | this.ClientSize = new System.Drawing.Size(431, 641); 71 | this.Controls.Add(this.splitContainer1); 72 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 73 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 74 | this.Name = "ConfirmationFormWeb"; 75 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 76 | this.Text = "Trade Confirmations"; 77 | this.splitContainer1.Panel1.ResumeLayout(false); 78 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); 79 | this.splitContainer1.ResumeLayout(false); 80 | this.ResumeLayout(false); 81 | 82 | } 83 | 84 | #endregion 85 | 86 | private System.Windows.Forms.SplitContainer splitContainer1; 87 | private System.Windows.Forms.Button btnRefresh; 88 | } 89 | } -------------------------------------------------------------------------------- /Steam Desktop Authenticator/WelcomeForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Data; 6 | using System.Drawing; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace Steam_Desktop_Authenticator 13 | { 14 | public partial class WelcomeForm : Form 15 | { 16 | private Manifest man; 17 | 18 | public WelcomeForm() 19 | { 20 | InitializeComponent(); 21 | man = Manifest.GetManifest(); 22 | } 23 | 24 | private void btnJustStart_Click(object sender, EventArgs e) 25 | { 26 | // Mark as not first run anymore 27 | man.FirstRun = false; 28 | man.Save(); 29 | 30 | showMainForm(); 31 | } 32 | 33 | private void btnImportConfig_Click(object sender, EventArgs e) 34 | { 35 | // Let the user select the config dir 36 | FolderBrowserDialog folderBrowser = new FolderBrowserDialog(); 37 | folderBrowser.Description = "Select the folder of your old Steam Desktop Authenticator install"; 38 | DialogResult userClickedOK = folderBrowser.ShowDialog(); 39 | 40 | if (userClickedOK == DialogResult.OK) 41 | { 42 | string path = folderBrowser.SelectedPath; 43 | string pathToCopy = null; 44 | 45 | if (Directory.Exists(path + "/maFiles")) 46 | { 47 | // User selected the root install dir 48 | pathToCopy = path + "/maFiles"; 49 | } 50 | else if (File.Exists(path + "/manifest.json")) 51 | { 52 | // User selected the maFiles dir 53 | pathToCopy = path; 54 | } 55 | else 56 | { 57 | // Could not find either. 58 | MessageBox.Show("This folder does not contain either a manifest.json or an maFiles folder.\nPlease select the location where you had Steam Desktop Authenticator installed.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 59 | return; 60 | } 61 | 62 | // Copy the contents of the config dir to the new config dir 63 | string currentPath = Manifest.GetExecutableDir(); 64 | 65 | // Create config dir if we don't have it 66 | if (!Directory.Exists(currentPath + "/maFiles")) 67 | { 68 | Directory.CreateDirectory(currentPath + "/maFiles"); 69 | } 70 | 71 | // Copy all files from the old dir to the new one 72 | foreach (string newPath in Directory.GetFiles(pathToCopy, "*.*", SearchOption.AllDirectories)) 73 | { 74 | File.Copy(newPath, newPath.Replace(pathToCopy, currentPath + "/maFiles"), true); 75 | } 76 | 77 | // Set first run in manifest 78 | try 79 | { 80 | man = Manifest.GetManifest(true); 81 | man.FirstRun = false; 82 | man.Save(); 83 | } 84 | catch (ManifestParseException) 85 | { 86 | // Manifest file was corrupted, generate a new one. 87 | try 88 | { 89 | MessageBox.Show("Your settings were unexpectedly corrupted and were reset to defaults.", "Steam Desktop Authenticator", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); 90 | man = Manifest.GenerateNewManifest(true); 91 | } 92 | catch (MaFileEncryptedException) 93 | { 94 | // An maFile was encrypted, we're fucked. 95 | MessageBox.Show("Sorry, but SDA was unable to recover your accounts since you used encryption.\nYou'll need to recover your Steam accounts by removing the authenticator.\nClick OK to view instructions.", "Steam Desktop Authenticator", MessageBoxButtons.OK, MessageBoxIcon.Error); 96 | System.Diagnostics.Process.Start(@"https://github.com/Jessecar96/SteamDesktopAuthenticator/wiki/Help!-I'm-locked-out-of-my-account"); 97 | this.Close(); 98 | return; 99 | } 100 | } 101 | 102 | // All done! 103 | MessageBox.Show("All accounts and settings have been imported! Click OK to continue.", "Import accounts", MessageBoxButtons.OK, MessageBoxIcon.Information); 104 | showMainForm(); 105 | } 106 | 107 | } 108 | 109 | private void showMainForm() 110 | { 111 | this.Hide(); 112 | new MainForm().Show(); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/ConfirmationFormWeb.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Data; 6 | using System.Drawing; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | using System.Diagnostics; 12 | using CefSharp; 13 | using CefSharp.WinForms; 14 | using SteamAuth; 15 | 16 | namespace Steam_Desktop_Authenticator 17 | { 18 | public partial class ConfirmationFormWeb : Form 19 | { 20 | private readonly ChromiumWebBrowser browser; 21 | private string steamCookies; 22 | private SteamGuardAccount steamAccount; 23 | private string tradeID; 24 | 25 | public ConfirmationFormWeb(SteamGuardAccount steamAccount) 26 | { 27 | InitializeComponent(); 28 | this.steamAccount = steamAccount; 29 | this.Text = String.Format("Trade Confirmations - {0}", steamAccount.AccountName); 30 | 31 | CefSettings settings = new CefSettings(); 32 | settings.PersistSessionCookies = false; 33 | settings.Locale = "en-US"; 34 | settings.UserAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 6P Build/XXXXX; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/47.0.2526.68 Mobile Safari/537.36"; 35 | steamCookies = String.Format("mobileClientVersion=0 (2.1.3); mobileClient=android; steamid={0}; steamLogin={1}; steamLoginSecure={2}; Steam_Language=english; dob=;", steamAccount.Session.SteamID.ToString(), steamAccount.Session.SteamLogin, steamAccount.Session.SteamLoginSecure); 36 | 37 | if (!Cef.IsInitialized) 38 | { 39 | Cef.Initialize(settings); 40 | } 41 | 42 | browser = new ChromiumWebBrowser(steamAccount.GenerateConfirmationURL()) 43 | { 44 | Dock = DockStyle.Fill, 45 | }; 46 | this.splitContainer1.Panel2.Controls.Add(browser); 47 | 48 | BrowserRequestHandler handler = new BrowserRequestHandler(); 49 | handler.Cookies = steamCookies; 50 | browser.RequestHandler = handler; 51 | browser.AddressChanged += Browser_AddressChanged; 52 | browser.LoadingStateChanged += Browser_LoadingStateChanged; 53 | } 54 | 55 | private void Browser_LoadingStateChanged(object sender, LoadingStateChangedEventArgs e) 56 | { 57 | // This looks really ugly, but it's easier than implementing steam's steammobile:// protocol using CefSharp 58 | // We override the page's GetValueFromLocalURL() to pass in the keys for sending ajax requests 59 | Debug.WriteLine("IsLoading: " + e.IsLoading); 60 | if (e.IsLoading == false) 61 | { 62 | // Generate url for details 63 | string urlParams = steamAccount.GenerateConfirmationQueryParams("details" + tradeID); 64 | 65 | var script = string.Format(@"window.GetValueFromLocalURL = 66 | function(url, timeout, success, error, fatal) {{ 67 | console.log(url); 68 | if(url.indexOf('steammobile://steamguard?op=conftag&arg1=allow') !== -1) {{ 69 | // send confirmation (allow) 70 | success('{0}'); 71 | }} else if(url.indexOf('steammobile://steamguard?op=conftag&arg1=cancel') !== -1) {{ 72 | // send confirmation (cancel) 73 | success('{1}'); 74 | }} else if(url.indexOf('steammobile://steamguard?op=conftag&arg1=details') !== -1) {{ 75 | // get details 76 | success('{2}'); 77 | }} 78 | }}", steamAccount.GenerateConfirmationQueryParams("allow"), steamAccount.GenerateConfirmationQueryParams("cancel"), urlParams); 79 | try 80 | { 81 | browser.ExecuteScriptAsync(script); 82 | } 83 | catch (Exception) 84 | { 85 | Debug.WriteLine("Failed to execute script"); 86 | } 87 | } 88 | } 89 | 90 | private void Browser_AddressChanged(object sender, AddressChangedEventArgs e) 91 | { 92 | string[] urlparts = browser.Address.Split('#'); 93 | if (urlparts.Length > 1) 94 | { 95 | tradeID = urlparts[1].Replace("conf_", ""); 96 | } 97 | } 98 | 99 | private void btnRefresh_Click(object sender, EventArgs e) 100 | { 101 | browser.Load(steamAccount.GenerateConfirmationURL()); 102 | } 103 | 104 | protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 105 | { 106 | bool bHandled = false; 107 | switch (keyData) 108 | { 109 | case Keys.F5: 110 | browser.Load(steamAccount.GenerateConfirmationURL()); 111 | bHandled = true; 112 | break; 113 | case Keys.F1: 114 | browser.ShowDevTools(); 115 | bHandled = true; 116 | break; 117 | } 118 | return bHandled; 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/InputForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Steam_Desktop_Authenticator 2 | { 3 | partial class InputForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InputForm)); 32 | this.labelText = new System.Windows.Forms.Label(); 33 | this.txtBox = new System.Windows.Forms.TextBox(); 34 | this.btnAccept = new System.Windows.Forms.Button(); 35 | this.btnCancel = new System.Windows.Forms.Button(); 36 | this.SuspendLayout(); 37 | // 38 | // labelText 39 | // 40 | this.labelText.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 41 | this.labelText.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 42 | this.labelText.ForeColor = System.Drawing.SystemColors.ControlText; 43 | this.labelText.Location = new System.Drawing.Point(12, 9); 44 | this.labelText.Name = "labelText"; 45 | this.labelText.Size = new System.Drawing.Size(383, 159); 46 | this.labelText.TabIndex = 0; 47 | this.labelText.Text = "Sample Text~~~"; 48 | // 49 | // txtBox 50 | // 51 | this.txtBox.Font = new System.Drawing.Font("Segoe UI", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 52 | this.txtBox.Location = new System.Drawing.Point(12, 171); 53 | this.txtBox.Name = "txtBox"; 54 | this.txtBox.Size = new System.Drawing.Size(383, 33); 55 | this.txtBox.TabIndex = 1; 56 | // 57 | // btnAccept 58 | // 59 | this.btnAccept.Location = new System.Drawing.Point(15, 210); 60 | this.btnAccept.Name = "btnAccept"; 61 | this.btnAccept.Size = new System.Drawing.Size(98, 28); 62 | this.btnAccept.TabIndex = 2; 63 | this.btnAccept.Text = "Accept"; 64 | this.btnAccept.UseVisualStyleBackColor = true; 65 | this.btnAccept.Click += new System.EventHandler(this.btnAccept_Click); 66 | // 67 | // btnCancel 68 | // 69 | this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; 70 | this.btnCancel.Location = new System.Drawing.Point(297, 210); 71 | this.btnCancel.Name = "btnCancel"; 72 | this.btnCancel.Size = new System.Drawing.Size(98, 28); 73 | this.btnCancel.TabIndex = 3; 74 | this.btnCancel.Text = "Cancel"; 75 | this.btnCancel.UseVisualStyleBackColor = true; 76 | this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); 77 | // 78 | // InputForm 79 | // 80 | this.AcceptButton = this.btnAccept; 81 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 82 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 83 | this.CancelButton = this.btnCancel; 84 | this.ClientSize = new System.Drawing.Size(407, 250); 85 | this.Controls.Add(this.btnCancel); 86 | this.Controls.Add(this.btnAccept); 87 | this.Controls.Add(this.txtBox); 88 | this.Controls.Add(this.labelText); 89 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 90 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 91 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 92 | this.MaximizeBox = false; 93 | this.Name = "InputForm"; 94 | this.ShowInTaskbar = false; 95 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 96 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.InputForm_FormClosing); 97 | this.ResumeLayout(false); 98 | this.PerformLayout(); 99 | 100 | } 101 | 102 | #endregion 103 | 104 | private System.Windows.Forms.Label labelText; 105 | public System.Windows.Forms.TextBox txtBox; 106 | private System.Windows.Forms.Button btnAccept; 107 | private System.Windows.Forms.Button btnCancel; 108 | } 109 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
4 | Steam Desktop Authenticator 5 |

6 |

7 | A desktop implementation of Steam's mobile authenticator app.
8 | We are not affiliated with Steam or Scrap.TF in any way! This project is run by community volunteers. 9 |

10 |

11 | WARNING: Recently there have been fake versions of SDA floating around that will steal your Steam account. Never download SDA from any place other than this github repo! 12 |

13 |

14 | Download here 15 |

16 |

Supports Windows 7 and up.

17 |
18 | 19 | **Clicking "Download ZIP" will not work!** This project uses git submodules so you must use git to download it properly. Using [GitHub Desktop](https://desktop.github.com/) is an easy way to do that. 20 | 21 | **DISCLAIMER: We provide no support for you when using Steam Desktop Authenticator! This project is run by community volunteers and is not affiliated with Steam or Scrap.TF. You use this program at your own risk, and accept the responsibility to make backups and prevent unauthorized access to your computer!** 22 | 23 | **REMEMBER: Always make backups of your `maFiles` directory! If you lose your encryption key or delete `maFiles` by accident AND you didn't save your revocation code, you are screwed.** 24 | 25 | **FINALLY: Using this application is a bad idea, because it COMPLETELY DEFEATS THE PURPOSE of two-factor authentication! If your desktop is infected with a virus, it will be able to hijack the authenticator app and completely subvert the protection. THIS APPLICATION DOES NOT PROTECT YOUR ACCOUNT; IT ONLY ALLOWS YOU TO USE STEAM FEATURES THAT REQUIRE THE AUTHENTICATOR WITHOUT HAVING A PHONE. If you have a phone that supports the Mobile Authenticator, you really shouldn't use this application!** 26 | 27 | IF you lost your `maFiles` OR lost your encryption key, go [here](https://store.steampowered.com/twofactor/manage) and click "Remove Authenticator" then enter your revocation code that you wrote down when you first added your account to SDA. 28 | 29 | If you did not follow the directions and did not write your revocation code down, you're well and truly screwed. The only option is beg to [Steam Support](https://support.steampowered.com/) and say you lost your mobile authenticator and the revocation code. 30 | 31 | ## Detailed setup instructions 32 | - Download & Install [.NET Framework 4.6.2](https://www.microsoft.com/net/download/dotnet-framework-runtime/net462) if you're using Windows 7. Windows 8 and above should do this automatically for you. 33 | - Visit [the releases page](https://github.com/Jessecar96/SteamDesktopAuthenticator/releases) and download the latest .zip (not the source code one). 34 | - Extract the files somewhere very safe on your computer. If you lose the files you can lose access to your Steam account. 35 | - Run `Steam Desktop Authenticator.exe` and click the button to set up a new account. 36 | - Login to Steam and follow the instructions to set it up. **Note: you still need a mobile phone that can receive SMS.** 37 | - You may be asked to set up encryption, this is to make sure if someone gains access to your computer they can't steal your Steam account from this program. This is optional but highly recommended. 38 | - Select your account from the list to view the current login code, and click `Trade Confirmations` to see pending trade confirmations. 39 | - For your safety, remember to get Steam Guard backup codes! Follow [this link](https://store.steampowered.com/twofactor/manage) and click "Get Backup Codes," then print out that page and save it in a safe place. You can use these codes if you lose access to your authenticator. 40 | 41 | [How to update SDA.](https://github.com/Jessecar96/SteamDesktopAuthenticator/wiki/Updating) 42 | 43 | [How to use SDA on multiple computers.](https://github.com/Jessecar96/SteamDesktopAuthenticator/wiki/Using-SDA-on-multiple-computers) 44 | 45 | 46 | ## Command line options 47 | ``` 48 | -k [encryption key] 49 | Set your encryption key when opened 50 | -s 51 | Auto-minimize to tray when opened 52 | ``` 53 | 54 | ## Troubleshooting 55 | - **Trade confirmation list is just white or a blank screen** 56 | - First open the "Selected Account" menu, then click "Force session refresh". If it still doesn't work after that, open the "Selected Account" menu again, then click "Login again" and login to your Steam account. 57 | 58 | If your problem doesn't appear on the list or none of the solutions worked, submit an issue on the issue tracker. When posting logs in an issue, please upload it to some site like [Pastebin](http://www.pastebin.com). 59 | 60 | ## Building on linux 61 | - First, you will need to install the `mono` and `monodevelop` packages, usually available from your standard package repository. 62 | - Open monodevelop and select File -> Open. Navigate to the folder where you cloned this program to and open the file "Steam Desktop Authenticator/Steam Desktop Authenticator.sln" 63 | - If you initialized submodules correctly, you should see two tree hirarchies on the left side of the screen, one labeled **SteamDesktopAuthenticator** and the other **SteamAuth**. (If you didn't, an error will be displayed; go update them!) For both of them, select "Packages", right click on "Newtonsoft.Json", and click update. Remember to do this for **both SteamDesktopAuthenticator and SteamAuth** 64 | - Select Project->Active Configuration->Release (this will make this application run faster) 65 | - Select Build->Build All. The package should now build successfully. 66 | - The resulting executable and files will be in "Steam Desktop Authenticator/bin/Release" 67 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/BrowserRequestHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using CefSharp; 8 | using System.Diagnostics; 9 | using System.IO; 10 | using Newtonsoft.Json; 11 | using System.Security.Cryptography.X509Certificates; 12 | 13 | namespace Steam_Desktop_Authenticator 14 | { 15 | class BrowserRequestHandler : IRequestHandler 16 | { 17 | public string Cookies; 18 | 19 | public static readonly string VersionNumberString = String.Format("Chromium: {0}, CEF: {1}, CefSharp: {2}", 20 | Cef.ChromiumVersion, Cef.CefVersion, Cef.CefSharpVersion); 21 | 22 | bool IRequestHandler.OnBeforeBrowse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, bool isRedirect) 23 | { 24 | return false; 25 | } 26 | 27 | bool IRequestHandler.OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture) 28 | { 29 | return OnOpenUrlFromTab(browserControl, browser, frame, targetUrl, targetDisposition, userGesture); 30 | } 31 | 32 | protected virtual bool OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture) 33 | { 34 | return false; 35 | } 36 | 37 | bool IRequestHandler.OnCertificateError(IWebBrowser browserControl, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback) 38 | { 39 | callback.Dispose(); 40 | return false; 41 | } 42 | 43 | void IRequestHandler.OnPluginCrashed(IWebBrowser browserControl, IBrowser browser, string pluginPath) 44 | { 45 | // TODO: Add your own code here for handling scenarios where a plugin crashed, for one reason or another. 46 | } 47 | 48 | CefReturnValue IRequestHandler.OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback) 49 | { 50 | // Check if the session is expired 51 | if (request.Url == "steammobile://lostauth") 52 | { 53 | MessageBox.Show("Failed to load confirmations.\nTry using \"Force session refresh\" under the Selected Account menu.\nIf that doesn't work use the \"Login again\" option.", "Confirmations", MessageBoxButtons.OK, MessageBoxIcon.Error); 54 | return CefReturnValue.Cancel; 55 | } 56 | 57 | // For some reason, in order to set cookies manually using a hdeader you need to clear the real cookies every time :/ 58 | Cef.GetGlobalCookieManager().VisitAllCookies(new DeleteAllCookiesVisitor()); 59 | 60 | if (request.Url.StartsWith("steammobile://")) 61 | { 62 | // Cancel all steammobile:// requests (for the app) 63 | return CefReturnValue.Cancel; 64 | } 65 | else 66 | { 67 | var headers = request.Headers; 68 | headers.Add("Cookie", Cookies); 69 | headers.Add("X-Requested-With", "com.valvesoftware.android.steam.community"); 70 | request.Headers = headers; 71 | return CefReturnValue.Continue; 72 | } 73 | } 74 | 75 | bool IRequestHandler.GetAuthCredentials(IWebBrowser browserControl, IBrowser browser, IFrame frame, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback) 76 | { 77 | callback.Dispose(); 78 | return false; 79 | } 80 | 81 | void IRequestHandler.OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status) 82 | { 83 | 84 | } 85 | 86 | bool IRequestHandler.OnQuotaRequest(IWebBrowser browserControl, IBrowser browser, string originUrl, long newSize, IRequestCallback callback) 87 | { 88 | return false; 89 | } 90 | 91 | bool IRequestHandler.OnProtocolExecution(IWebBrowser browserControl, IBrowser browser, string url) 92 | { 93 | return false; 94 | } 95 | 96 | void IRequestHandler.OnRenderViewReady(IWebBrowser browserControl, IBrowser browser) 97 | { 98 | 99 | } 100 | 101 | bool IRequestHandler.OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response) 102 | { 103 | return false; 104 | } 105 | 106 | public void OnResourceLoadComplete(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength) 107 | { 108 | 109 | } 110 | 111 | public IResponseFilter GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response) 112 | { 113 | return new ResourceResponseFilter(); 114 | } 115 | 116 | public bool OnSelectClientCertificate(IWebBrowser browserControl, IBrowser browser, bool isProxy, string host, int port, X509Certificate2Collection certificates, ISelectClientCertificateCallback callback) 117 | { 118 | return true; 119 | } 120 | 121 | public void OnResourceRedirect(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl) 122 | { 123 | 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/ImportAccountForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Steam_Desktop_Authenticator 2 | { 3 | partial class ImportAccountForm 4 | { 5 | #region Windows Form Designer generated code 6 | 7 | /// 8 | /// Required method for Designer support - do not modify 9 | /// the contents of this method with the code editor. 10 | /// 11 | private void InitializeComponent() 12 | { 13 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ImportAccountForm)); 14 | this.labelText = new System.Windows.Forms.Label(); 15 | this.txtBox = new System.Windows.Forms.TextBox(); 16 | this.btnImport = new System.Windows.Forms.Button(); 17 | this.btnCancel = new System.Windows.Forms.Button(); 18 | this.label1 = new System.Windows.Forms.Label(); 19 | this.SuspendLayout(); 20 | // 21 | // labelText 22 | // 23 | this.labelText.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 24 | this.labelText.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 25 | this.labelText.ForeColor = System.Drawing.SystemColors.ControlText; 26 | this.labelText.Location = new System.Drawing.Point(15, 14); 27 | this.labelText.Name = "labelText"; 28 | this.labelText.Size = new System.Drawing.Size(317, 25); 29 | this.labelText.TabIndex = 0; 30 | this.labelText.Text = "Enter your encryption passkey if your .maFile is encrypted:"; 31 | // 32 | // txtBox 33 | // 34 | this.txtBox.Font = new System.Drawing.Font("Segoe UI", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 35 | this.txtBox.Location = new System.Drawing.Point(15, 42); 36 | this.txtBox.Name = "txtBox"; 37 | this.txtBox.Size = new System.Drawing.Size(307, 33); 38 | this.txtBox.TabIndex = 1; 39 | // 40 | // btnImport 41 | // 42 | this.btnImport.Location = new System.Drawing.Point(135, 131); 43 | this.btnImport.Name = "btnImport"; 44 | this.btnImport.Size = new System.Drawing.Size(187, 28); 45 | this.btnImport.TabIndex = 3; 46 | this.btnImport.Text = "Select .maFile file to Import"; 47 | this.btnImport.UseVisualStyleBackColor = true; 48 | this.btnImport.Click += new System.EventHandler(this.btnImport_Click); 49 | // 50 | // btnCancel 51 | // 52 | this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; 53 | this.btnCancel.Location = new System.Drawing.Point(41, 131); 54 | this.btnCancel.Name = "btnCancel"; 55 | this.btnCancel.Size = new System.Drawing.Size(88, 28); 56 | this.btnCancel.TabIndex = 4; 57 | this.btnCancel.Text = "Cancel"; 58 | this.btnCancel.UseVisualStyleBackColor = true; 59 | this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); 60 | // 61 | // label1 62 | // 63 | this.label1.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 64 | this.label1.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 65 | this.label1.ForeColor = System.Drawing.SystemColors.ControlText; 66 | this.label1.Location = new System.Drawing.Point(15, 83); 67 | this.label1.Name = "label1"; 68 | this.label1.Size = new System.Drawing.Size(307, 40); 69 | this.label1.TabIndex = 2; 70 | this.label1.Text = "If you import an encrypted .maFile, the manifest file must be next to it."; 71 | // 72 | // ImportAccountForm 73 | // 74 | this.AcceptButton = this.btnImport; 75 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 76 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 77 | this.CancelButton = this.btnCancel; 78 | this.ClientSize = new System.Drawing.Size(336, 171); 79 | this.Controls.Add(this.label1); 80 | this.Controls.Add(this.btnCancel); 81 | this.Controls.Add(this.btnImport); 82 | this.Controls.Add(this.txtBox); 83 | this.Controls.Add(this.labelText); 84 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 85 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 86 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 87 | this.MaximizeBox = false; 88 | this.Name = "ImportAccountForm"; 89 | this.ShowInTaskbar = false; 90 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 91 | this.Text = "Import Account"; 92 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Import_maFile_Form_FormClosing); 93 | this.ResumeLayout(false); 94 | this.PerformLayout(); 95 | 96 | } 97 | 98 | #endregion 99 | 100 | private System.Windows.Forms.Label labelText; 101 | private System.Windows.Forms.TextBox txtBox; 102 | private System.Windows.Forms.Button btnImport; 103 | private System.Windows.Forms.Button btnCancel; 104 | private System.Windows.Forms.Label label1; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/WelcomeForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Steam_Desktop_Authenticator 2 | { 3 | partial class WelcomeForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WelcomeForm)); 32 | this.label1 = new System.Windows.Forms.Label(); 33 | this.btnImportConfig = new System.Windows.Forms.Button(); 34 | this.label2 = new System.Windows.Forms.Label(); 35 | this.btnJustStart = new System.Windows.Forms.Button(); 36 | this.SuspendLayout(); 37 | // 38 | // label1 39 | // 40 | this.label1.Font = new System.Drawing.Font("Segoe UI", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 41 | this.label1.Location = new System.Drawing.Point(12, 9); 42 | this.label1.Name = "label1"; 43 | this.label1.Size = new System.Drawing.Size(366, 73); 44 | this.label1.TabIndex = 0; 45 | this.label1.Text = "Welcome to\r\nSteam Desktop Authenticator"; 46 | this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 47 | // 48 | // btnImportConfig 49 | // 50 | this.btnImportConfig.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 51 | this.btnImportConfig.Location = new System.Drawing.Point(12, 134); 52 | this.btnImportConfig.Name = "btnImportConfig"; 53 | this.btnImportConfig.Size = new System.Drawing.Size(366, 51); 54 | this.btnImportConfig.TabIndex = 1; 55 | this.btnImportConfig.Text = "I already setup Steam Desktop Authenticator in another location on this PC and I " + 56 | "want to import its account(s).\r\n"; 57 | this.btnImportConfig.UseVisualStyleBackColor = true; 58 | this.btnImportConfig.Click += new System.EventHandler(this.btnImportConfig_Click); 59 | // 60 | // label2 61 | // 62 | this.label2.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 63 | this.label2.Location = new System.Drawing.Point(12, 86); 64 | this.label2.Name = "label2"; 65 | this.label2.Size = new System.Drawing.Size(366, 37); 66 | this.label2.TabIndex = 2; 67 | this.label2.Text = "Select an item to get started:"; 68 | this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 69 | // 70 | // btnJustStart 71 | // 72 | this.btnJustStart.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 73 | this.btnJustStart.Location = new System.Drawing.Point(12, 191); 74 | this.btnJustStart.Name = "btnJustStart"; 75 | this.btnJustStart.Size = new System.Drawing.Size(366, 52); 76 | this.btnJustStart.TabIndex = 4; 77 | this.btnJustStart.Text = "This is my first time and \r\nI just want to sign into my Steam Account(s)."; 78 | this.btnJustStart.UseVisualStyleBackColor = true; 79 | this.btnJustStart.Click += new System.EventHandler(this.btnJustStart_Click); 80 | // 81 | // WelcomeForm 82 | // 83 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 84 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 85 | this.ClientSize = new System.Drawing.Size(390, 255); 86 | this.Controls.Add(this.btnJustStart); 87 | this.Controls.Add(this.label2); 88 | this.Controls.Add(this.btnImportConfig); 89 | this.Controls.Add(this.label1); 90 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 91 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 92 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 93 | this.MaximizeBox = false; 94 | this.Name = "WelcomeForm"; 95 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 96 | this.Text = "Steam Desktop Authenticator"; 97 | this.ResumeLayout(false); 98 | 99 | } 100 | 101 | #endregion 102 | 103 | private System.Windows.Forms.Label label1; 104 | private System.Windows.Forms.Button btnImportConfig; 105 | private System.Windows.Forms.Label label2; 106 | private System.Windows.Forms.Button btnJustStart; 107 | } 108 | } -------------------------------------------------------------------------------- /Steam Desktop Authenticator/CaptchaForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Steam_Desktop_Authenticator 2 | { 3 | partial class CaptchaForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CaptchaForm)); 32 | this.labelText = new System.Windows.Forms.Label(); 33 | this.txtBox = new System.Windows.Forms.TextBox(); 34 | this.btnAccept = new System.Windows.Forms.Button(); 35 | this.btnCancel = new System.Windows.Forms.Button(); 36 | this.pictureBoxCaptcha = new System.Windows.Forms.PictureBox(); 37 | ((System.ComponentModel.ISupportInitialize)(this.pictureBoxCaptcha)).BeginInit(); 38 | this.SuspendLayout(); 39 | // 40 | // labelText 41 | // 42 | this.labelText.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 43 | this.labelText.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 44 | this.labelText.ForeColor = System.Drawing.SystemColors.ControlText; 45 | this.labelText.Location = new System.Drawing.Point(-1, 14); 46 | this.labelText.Name = "labelText"; 47 | this.labelText.Size = new System.Drawing.Size(233, 18); 48 | this.labelText.TabIndex = 0; 49 | this.labelText.Text = "Please enter the following captcha code:"; 50 | this.labelText.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 51 | // 52 | // txtBox 53 | // 54 | this.txtBox.Font = new System.Drawing.Font("Segoe UI", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 55 | this.txtBox.Location = new System.Drawing.Point(12, 84); 56 | this.txtBox.Name = "txtBox"; 57 | this.txtBox.Size = new System.Drawing.Size(206, 33); 58 | this.txtBox.TabIndex = 1; 59 | // 60 | // btnAccept 61 | // 62 | this.btnAccept.Location = new System.Drawing.Point(11, 123); 63 | this.btnAccept.Name = "btnAccept"; 64 | this.btnAccept.Size = new System.Drawing.Size(98, 28); 65 | this.btnAccept.TabIndex = 2; 66 | this.btnAccept.Text = "Submit"; 67 | this.btnAccept.UseVisualStyleBackColor = true; 68 | this.btnAccept.Click += new System.EventHandler(this.btnAccept_Click); 69 | // 70 | // btnCancel 71 | // 72 | this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; 73 | this.btnCancel.Location = new System.Drawing.Point(120, 123); 74 | this.btnCancel.Name = "btnCancel"; 75 | this.btnCancel.Size = new System.Drawing.Size(98, 28); 76 | this.btnCancel.TabIndex = 3; 77 | this.btnCancel.Text = "Cancel"; 78 | this.btnCancel.UseVisualStyleBackColor = true; 79 | this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); 80 | // 81 | // pictureBoxCaptcha 82 | // 83 | this.pictureBoxCaptcha.Location = new System.Drawing.Point(12, 37); 84 | this.pictureBoxCaptcha.Name = "pictureBoxCaptcha"; 85 | this.pictureBoxCaptcha.Size = new System.Drawing.Size(206, 40); 86 | this.pictureBoxCaptcha.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; 87 | this.pictureBoxCaptcha.TabIndex = 4; 88 | this.pictureBoxCaptcha.TabStop = false; 89 | // 90 | // CaptchaForm 91 | // 92 | this.AcceptButton = this.btnAccept; 93 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 94 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 95 | this.CancelButton = this.btnCancel; 96 | this.ClientSize = new System.Drawing.Size(232, 164); 97 | this.Controls.Add(this.pictureBoxCaptcha); 98 | this.Controls.Add(this.btnCancel); 99 | this.Controls.Add(this.btnAccept); 100 | this.Controls.Add(this.txtBox); 101 | this.Controls.Add(this.labelText); 102 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 103 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 104 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 105 | this.Name = "CaptchaForm"; 106 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 107 | ((System.ComponentModel.ISupportInitialize)(this.pictureBoxCaptcha)).EndInit(); 108 | this.ResumeLayout(false); 109 | this.PerformLayout(); 110 | 111 | } 112 | 113 | #endregion 114 | 115 | private System.Windows.Forms.Label labelText; 116 | public System.Windows.Forms.TextBox txtBox; 117 | private System.Windows.Forms.Button btnAccept; 118 | private System.Windows.Forms.Button btnCancel; 119 | private System.Windows.Forms.PictureBox pictureBoxCaptcha; 120 | } 121 | } -------------------------------------------------------------------------------- /Steam Desktop Authenticator/TradePopupForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Steam_Desktop_Authenticator 2 | { 3 | partial class TradePopupForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TradePopupForm)); 32 | this.lblDesc = new System.Windows.Forms.Label(); 33 | this.btnDeny = new System.Windows.Forms.Button(); 34 | this.btnAccept = new System.Windows.Forms.Button(); 35 | this.lblStatus = new System.Windows.Forms.Label(); 36 | this.lblAccount = new System.Windows.Forms.Label(); 37 | this.SuspendLayout(); 38 | // 39 | // lblDesc 40 | // 41 | this.lblDesc.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 42 | this.lblDesc.Location = new System.Drawing.Point(12, 23); 43 | this.lblDesc.Name = "lblDesc"; 44 | this.lblDesc.Size = new System.Drawing.Size(142, 38); 45 | this.lblDesc.TabIndex = 1; 46 | this.lblDesc.Text = "trade description"; 47 | this.lblDesc.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 48 | // 49 | // btnDeny 50 | // 51 | this.btnDeny.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(192)))), ((int)(((byte)(192))))); 52 | this.btnDeny.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 53 | this.btnDeny.Location = new System.Drawing.Point(12, 87); 54 | this.btnDeny.Name = "btnDeny"; 55 | this.btnDeny.Size = new System.Drawing.Size(69, 32); 56 | this.btnDeny.TabIndex = 2; 57 | this.btnDeny.Text = "Deny"; 58 | this.btnDeny.UseVisualStyleBackColor = false; 59 | this.btnDeny.Click += new System.EventHandler(this.btnDeny_Click); 60 | // 61 | // btnAccept 62 | // 63 | this.btnAccept.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(192))))); 64 | this.btnAccept.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 65 | this.btnAccept.Location = new System.Drawing.Point(87, 87); 66 | this.btnAccept.Name = "btnAccept"; 67 | this.btnAccept.Size = new System.Drawing.Size(67, 32); 68 | this.btnAccept.TabIndex = 2; 69 | this.btnAccept.Text = "Accept"; 70 | this.btnAccept.UseVisualStyleBackColor = false; 71 | this.btnAccept.Click += new System.EventHandler(this.btnAccept_Click); 72 | // 73 | // lblStatus 74 | // 75 | this.lblStatus.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 76 | this.lblStatus.Location = new System.Drawing.Point(0, 61); 77 | this.lblStatus.Name = "lblStatus"; 78 | this.lblStatus.Size = new System.Drawing.Size(166, 19); 79 | this.lblStatus.TabIndex = 3; 80 | this.lblStatus.Text = "status"; 81 | this.lblStatus.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 82 | // 83 | // lblAccount 84 | // 85 | this.lblAccount.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 86 | this.lblAccount.Location = new System.Drawing.Point(12, 0); 87 | this.lblAccount.Name = "lblAccount"; 88 | this.lblAccount.Size = new System.Drawing.Size(142, 23); 89 | this.lblAccount.TabIndex = 4; 90 | this.lblAccount.Text = "account name"; 91 | this.lblAccount.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 92 | // 93 | // TradePopupForm 94 | // 95 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 96 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 97 | this.ClientSize = new System.Drawing.Size(166, 131); 98 | this.Controls.Add(this.lblAccount); 99 | this.Controls.Add(this.lblStatus); 100 | this.Controls.Add(this.btnAccept); 101 | this.Controls.Add(this.btnDeny); 102 | this.Controls.Add(this.lblDesc); 103 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 104 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; 105 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 106 | this.Name = "TradePopupForm"; 107 | this.Text = "New confirmation"; 108 | this.TopMost = true; 109 | this.Load += new System.EventHandler(this.TradePopupForm_Load); 110 | this.ResumeLayout(false); 111 | 112 | } 113 | 114 | #endregion 115 | private System.Windows.Forms.Label lblDesc; 116 | private System.Windows.Forms.Button btnDeny; 117 | private System.Windows.Forms.Button btnAccept; 118 | private System.Windows.Forms.Label lblStatus; 119 | private System.Windows.Forms.Label lblAccount; 120 | } 121 | } -------------------------------------------------------------------------------- /Steam Desktop Authenticator/LoginForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Steam_Desktop_Authenticator 2 | { 3 | partial class LoginForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LoginForm)); 32 | this.label1 = new System.Windows.Forms.Label(); 33 | this.txtUsername = new System.Windows.Forms.TextBox(); 34 | this.txtPassword = new System.Windows.Forms.TextBox(); 35 | this.label2 = new System.Windows.Forms.Label(); 36 | this.btnSteamLogin = new System.Windows.Forms.Button(); 37 | this.labelLoginExplanation = new System.Windows.Forms.Label(); 38 | this.SuspendLayout(); 39 | // 40 | // label1 41 | // 42 | this.label1.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 43 | this.label1.ForeColor = System.Drawing.SystemColors.ControlText; 44 | this.label1.Location = new System.Drawing.Point(12, 30); 45 | this.label1.Name = "label1"; 46 | this.label1.Size = new System.Drawing.Size(86, 25); 47 | this.label1.TabIndex = 0; 48 | this.label1.Text = "Username:"; 49 | this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight; 50 | // 51 | // txtUsername 52 | // 53 | this.txtUsername.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 54 | this.txtUsername.Location = new System.Drawing.Point(101, 31); 55 | this.txtUsername.Name = "txtUsername"; 56 | this.txtUsername.Size = new System.Drawing.Size(220, 25); 57 | this.txtUsername.TabIndex = 1; 58 | // 59 | // txtPassword 60 | // 61 | this.txtPassword.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 62 | this.txtPassword.Location = new System.Drawing.Point(101, 63); 63 | this.txtPassword.Name = "txtPassword"; 64 | this.txtPassword.PasswordChar = '*'; 65 | this.txtPassword.Size = new System.Drawing.Size(220, 25); 66 | this.txtPassword.TabIndex = 3; 67 | // 68 | // label2 69 | // 70 | this.label2.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 71 | this.label2.ForeColor = System.Drawing.SystemColors.ControlText; 72 | this.label2.Location = new System.Drawing.Point(12, 62); 73 | this.label2.Name = "label2"; 74 | this.label2.Size = new System.Drawing.Size(83, 25); 75 | this.label2.TabIndex = 2; 76 | this.label2.Text = "Password:"; 77 | this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight; 78 | // 79 | // btnSteamLogin 80 | // 81 | this.btnSteamLogin.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 82 | this.btnSteamLogin.Location = new System.Drawing.Point(224, 147); 83 | this.btnSteamLogin.Name = "btnSteamLogin"; 84 | this.btnSteamLogin.Size = new System.Drawing.Size(110, 33); 85 | this.btnSteamLogin.TabIndex = 4; 86 | this.btnSteamLogin.Text = "Login"; 87 | this.btnSteamLogin.UseVisualStyleBackColor = true; 88 | this.btnSteamLogin.Click += new System.EventHandler(this.btnSteamLogin_Click); 89 | // 90 | // labelLoginExplanation 91 | // 92 | this.labelLoginExplanation.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 93 | this.labelLoginExplanation.Location = new System.Drawing.Point(15, 98); 94 | this.labelLoginExplanation.Name = "labelLoginExplanation"; 95 | this.labelLoginExplanation.Size = new System.Drawing.Size(306, 46); 96 | this.labelLoginExplanation.TabIndex = 5; 97 | this.labelLoginExplanation.Text = "This will activate Steam Desktop Authenticator on your Steam account. This requir" + 98 | "es a phone number that can receive SMS."; 99 | // 100 | // LoginForm 101 | // 102 | this.AcceptButton = this.btnSteamLogin; 103 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 104 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 105 | this.ClientSize = new System.Drawing.Size(346, 193); 106 | this.Controls.Add(this.labelLoginExplanation); 107 | this.Controls.Add(this.btnSteamLogin); 108 | this.Controls.Add(this.txtPassword); 109 | this.Controls.Add(this.label2); 110 | this.Controls.Add(this.txtUsername); 111 | this.Controls.Add(this.label1); 112 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 113 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 114 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 115 | this.ImeMode = System.Windows.Forms.ImeMode.On; 116 | this.MaximizeBox = false; 117 | this.Name = "LoginForm"; 118 | this.ShowIcon = false; 119 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 120 | this.Text = "Steam Login"; 121 | this.Load += new System.EventHandler(this.LoginForm_Load); 122 | this.ResumeLayout(false); 123 | this.PerformLayout(); 124 | 125 | } 126 | 127 | #endregion 128 | 129 | private System.Windows.Forms.Label label1; 130 | private System.Windows.Forms.TextBox txtUsername; 131 | private System.Windows.Forms.TextBox txtPassword; 132 | private System.Windows.Forms.Label label2; 133 | private System.Windows.Forms.Button btnSteamLogin; 134 | private System.Windows.Forms.Label labelLoginExplanation; 135 | } 136 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Coverlet is a free, cross platform Code Coverage Tool 141 | coverage*[.json, .xml, .info] 142 | 143 | # Visual Studio code coverage results 144 | *.coverage 145 | *.coveragexml 146 | 147 | # NCrunch 148 | _NCrunch_* 149 | .*crunch*.local.xml 150 | nCrunchTemp_* 151 | 152 | # MightyMoose 153 | *.mm.* 154 | AutoTest.Net/ 155 | 156 | # Web workbench (sass) 157 | .sass-cache/ 158 | 159 | # Installshield output folder 160 | [Ee]xpress/ 161 | 162 | # DocProject is a documentation generator add-in 163 | DocProject/buildhelp/ 164 | DocProject/Help/*.HxT 165 | DocProject/Help/*.HxC 166 | DocProject/Help/*.hhc 167 | DocProject/Help/*.hhk 168 | DocProject/Help/*.hhp 169 | DocProject/Help/Html2 170 | DocProject/Help/html 171 | 172 | # Click-Once directory 173 | publish/ 174 | 175 | # Publish Web Output 176 | *.[Pp]ublish.xml 177 | *.azurePubxml 178 | # Note: Comment the next line if you want to checkin your web deploy settings, 179 | # but database connection strings (with potential passwords) will be unencrypted 180 | *.pubxml 181 | *.publishproj 182 | 183 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 184 | # checkin your Azure Web App publish settings, but sensitive information contained 185 | # in these scripts will be unencrypted 186 | PublishScripts/ 187 | 188 | # NuGet Packages 189 | *.nupkg 190 | # NuGet Symbol Packages 191 | *.snupkg 192 | # The packages folder can be ignored because of Package Restore 193 | **/[Pp]ackages/* 194 | # except build/, which is used as an MSBuild target. 195 | !**/[Pp]ackages/build/ 196 | # Uncomment if necessary however generally it will be regenerated when needed 197 | #!**/[Pp]ackages/repositories.config 198 | # NuGet v3's project.json files produces more ignorable files 199 | *.nuget.props 200 | *.nuget.targets 201 | 202 | # Microsoft Azure Build Output 203 | csx/ 204 | *.build.csdef 205 | 206 | # Microsoft Azure Emulator 207 | ecf/ 208 | rcf/ 209 | 210 | # Windows Store app package directories and files 211 | AppPackages/ 212 | BundleArtifacts/ 213 | Package.StoreAssociation.xml 214 | _pkginfo.txt 215 | *.appx 216 | *.appxbundle 217 | *.appxupload 218 | 219 | # Visual Studio cache files 220 | # files ending in .cache can be ignored 221 | *.[Cc]ache 222 | # but keep track of directories ending in .cache 223 | !?*.[Cc]ache/ 224 | 225 | # Others 226 | ClientBin/ 227 | ~$* 228 | *~ 229 | *.dbmdl 230 | *.dbproj.schemaview 231 | *.jfm 232 | *.pfx 233 | *.publishsettings 234 | orleans.codegen.cs 235 | 236 | # Including strong name files can present a security risk 237 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 238 | #*.snk 239 | 240 | # Since there are multiple workflows, uncomment next line to ignore bower_components 241 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 242 | #bower_components/ 243 | 244 | # RIA/Silverlight projects 245 | Generated_Code/ 246 | 247 | # Backup & report files from converting an old project file 248 | # to a newer Visual Studio version. Backup files are not needed, 249 | # because we have git ;-) 250 | _UpgradeReport_Files/ 251 | Backup*/ 252 | UpgradeLog*.XML 253 | UpgradeLog*.htm 254 | ServiceFabricBackup/ 255 | *.rptproj.bak 256 | 257 | # SQL Server files 258 | *.mdf 259 | *.ldf 260 | *.ndf 261 | 262 | # Business Intelligence projects 263 | *.rdl.data 264 | *.bim.layout 265 | *.bim_*.settings 266 | *.rptproj.rsuser 267 | *- [Bb]ackup.rdl 268 | *- [Bb]ackup ([0-9]).rdl 269 | *- [Bb]ackup ([0-9][0-9]).rdl 270 | 271 | # Microsoft Fakes 272 | FakesAssemblies/ 273 | 274 | # GhostDoc plugin setting file 275 | *.GhostDoc.xml 276 | 277 | # Node.js Tools for Visual Studio 278 | .ntvs_analysis.dat 279 | node_modules/ 280 | 281 | # Visual Studio 6 build log 282 | *.plg 283 | 284 | # Visual Studio 6 workspace options file 285 | *.opt 286 | 287 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 288 | *.vbw 289 | 290 | # Visual Studio LightSwitch build output 291 | **/*.HTMLClient/GeneratedArtifacts 292 | **/*.DesktopClient/GeneratedArtifacts 293 | **/*.DesktopClient/ModelManifest.xml 294 | **/*.Server/GeneratedArtifacts 295 | **/*.Server/ModelManifest.xml 296 | _Pvt_Extensions 297 | 298 | # Paket dependency manager 299 | .paket/paket.exe 300 | paket-files/ 301 | 302 | # FAKE - F# Make 303 | .fake/ 304 | 305 | # CodeRush personal settings 306 | .cr/personal 307 | 308 | # Python Tools for Visual Studio (PTVS) 309 | __pycache__/ 310 | *.pyc 311 | 312 | # Cake - Uncomment if you are using it 313 | # tools/** 314 | # !tools/packages.config 315 | 316 | # Tabs Studio 317 | *.tss 318 | 319 | # Telerik's JustMock configuration file 320 | *.jmconfig 321 | 322 | # BizTalk build output 323 | *.btp.cs 324 | *.btm.cs 325 | *.odx.cs 326 | *.xsd.cs 327 | 328 | # OpenCover UI analysis results 329 | OpenCover/ 330 | 331 | # Azure Stream Analytics local run output 332 | ASALocalRun/ 333 | 334 | # MSBuild Binary and Structured Log 335 | *.binlog 336 | 337 | # NVidia Nsight GPU debugger configuration file 338 | *.nvuser 339 | 340 | # MFractors (Xamarin productivity tool) working folder 341 | .mfractor/ 342 | 343 | # Local History for Visual Studio 344 | .localhistory/ 345 | 346 | # BeatPulse healthcheck temp database 347 | healthchecksdb 348 | 349 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 350 | MigrationBackup/ 351 | 352 | # Ionide (cross platform F# VS Code tools) working folder 353 | .ionide/ -------------------------------------------------------------------------------- /Steam Desktop Authenticator/SettingsForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Steam_Desktop_Authenticator 2 | { 3 | partial class SettingsForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SettingsForm)); 32 | this.chkPeriodicChecking = new System.Windows.Forms.CheckBox(); 33 | this.btnSave = new System.Windows.Forms.Button(); 34 | this.numPeriodicInterval = new System.Windows.Forms.NumericUpDown(); 35 | this.label1 = new System.Windows.Forms.Label(); 36 | this.chkCheckAll = new System.Windows.Forms.CheckBox(); 37 | this.chkConfirmMarket = new System.Windows.Forms.CheckBox(); 38 | this.chkConfirmTrades = new System.Windows.Forms.CheckBox(); 39 | ((System.ComponentModel.ISupportInitialize)(this.numPeriodicInterval)).BeginInit(); 40 | this.SuspendLayout(); 41 | // 42 | // chkPeriodicChecking 43 | // 44 | this.chkPeriodicChecking.AutoSize = true; 45 | this.chkPeriodicChecking.Location = new System.Drawing.Point(12, 12); 46 | this.chkPeriodicChecking.Name = "chkPeriodicChecking"; 47 | this.chkPeriodicChecking.Size = new System.Drawing.Size(233, 30); 48 | this.chkPeriodicChecking.TabIndex = 0; 49 | this.chkPeriodicChecking.Text = "Periodically check for new confirmations\r\nand show a popup when they arrive"; 50 | this.chkPeriodicChecking.UseVisualStyleBackColor = true; 51 | this.chkPeriodicChecking.CheckedChanged += new System.EventHandler(this.chkPeriodicChecking_CheckedChanged); 52 | // 53 | // btnSave 54 | // 55 | this.btnSave.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 56 | | System.Windows.Forms.AnchorStyles.Right))); 57 | this.btnSave.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 58 | this.btnSave.Location = new System.Drawing.Point(12, 152); 59 | this.btnSave.Name = "btnSave"; 60 | this.btnSave.Size = new System.Drawing.Size(224, 38); 61 | this.btnSave.TabIndex = 1; 62 | this.btnSave.Text = "Save"; 63 | this.btnSave.UseVisualStyleBackColor = true; 64 | this.btnSave.Click += new System.EventHandler(this.btnSave_Click); 65 | // 66 | // numPeriodicInterval 67 | // 68 | this.numPeriodicInterval.Location = new System.Drawing.Point(12, 51); 69 | this.numPeriodicInterval.Minimum = new decimal(new int[] { 70 | 5, 71 | 0, 72 | 0, 73 | 0}); 74 | this.numPeriodicInterval.Name = "numPeriodicInterval"; 75 | this.numPeriodicInterval.Size = new System.Drawing.Size(41, 22); 76 | this.numPeriodicInterval.TabIndex = 2; 77 | this.numPeriodicInterval.Value = new decimal(new int[] { 78 | 5, 79 | 0, 80 | 0, 81 | 0}); 82 | // 83 | // label1 84 | // 85 | this.label1.AutoSize = true; 86 | this.label1.Location = new System.Drawing.Point(59, 49); 87 | this.label1.Name = "label1"; 88 | this.label1.Size = new System.Drawing.Size(150, 26); 89 | this.label1.TabIndex = 3; 90 | this.label1.Text = "Seconds between checking \r\nfor confirmations"; 91 | // 92 | // chkCheckAll 93 | // 94 | this.chkCheckAll.AutoSize = true; 95 | this.chkCheckAll.Location = new System.Drawing.Point(12, 81); 96 | this.chkCheckAll.Name = "chkCheckAll"; 97 | this.chkCheckAll.Size = new System.Drawing.Size(213, 17); 98 | this.chkCheckAll.TabIndex = 4; 99 | this.chkCheckAll.Text = "Check all accounts for confirmations"; 100 | this.chkCheckAll.UseVisualStyleBackColor = true; 101 | // 102 | // chkConfirmMarket 103 | // 104 | this.chkConfirmMarket.AutoSize = true; 105 | this.chkConfirmMarket.Location = new System.Drawing.Point(12, 104); 106 | this.chkConfirmMarket.Name = "chkConfirmMarket"; 107 | this.chkConfirmMarket.Size = new System.Drawing.Size(198, 17); 108 | this.chkConfirmMarket.TabIndex = 5; 109 | this.chkConfirmMarket.Text = "Auto-confirm market transactions"; 110 | this.chkConfirmMarket.UseVisualStyleBackColor = true; 111 | this.chkConfirmMarket.CheckedChanged += new System.EventHandler(this.chkConfirmMarket_CheckedChanged); 112 | // 113 | // chkConfirmTrades 114 | // 115 | this.chkConfirmTrades.AutoSize = true; 116 | this.chkConfirmTrades.Location = new System.Drawing.Point(12, 127); 117 | this.chkConfirmTrades.Name = "chkConfirmTrades"; 118 | this.chkConfirmTrades.Size = new System.Drawing.Size(129, 17); 119 | this.chkConfirmTrades.TabIndex = 6; 120 | this.chkConfirmTrades.Text = "Auto-confirm trades"; 121 | this.chkConfirmTrades.UseVisualStyleBackColor = true; 122 | this.chkConfirmTrades.CheckedChanged += new System.EventHandler(this.chkConfirmTrades_CheckedChanged); 123 | // 124 | // SettingsForm 125 | // 126 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 127 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 128 | this.ClientSize = new System.Drawing.Size(244, 202); 129 | this.Controls.Add(this.chkConfirmTrades); 130 | this.Controls.Add(this.chkConfirmMarket); 131 | this.Controls.Add(this.chkCheckAll); 132 | this.Controls.Add(this.label1); 133 | this.Controls.Add(this.numPeriodicInterval); 134 | this.Controls.Add(this.btnSave); 135 | this.Controls.Add(this.chkPeriodicChecking); 136 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 137 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 138 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 139 | this.MaximizeBox = false; 140 | this.Name = "SettingsForm"; 141 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 142 | this.Text = "Settings"; 143 | ((System.ComponentModel.ISupportInitialize)(this.numPeriodicInterval)).EndInit(); 144 | this.ResumeLayout(false); 145 | this.PerformLayout(); 146 | 147 | } 148 | 149 | #endregion 150 | 151 | private System.Windows.Forms.CheckBox chkPeriodicChecking; 152 | private System.Windows.Forms.Button btnSave; 153 | private System.Windows.Forms.NumericUpDown numPeriodicInterval; 154 | private System.Windows.Forms.Label label1; 155 | private System.Windows.Forms.CheckBox chkCheckAll; 156 | private System.Windows.Forms.CheckBox chkConfirmMarket; 157 | private System.Windows.Forms.CheckBox chkConfirmTrades; 158 | } 159 | } -------------------------------------------------------------------------------- /Steam Desktop Authenticator/FileEncryptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Security.Cryptography; 7 | using System.IO; 8 | 9 | namespace Steam_Desktop_Authenticator 10 | { 11 | /// 12 | /// This class provides the controls that will encrypt and decrypt the *.maFile files 13 | /// 14 | /// Passwords entered will be passed into 100k rounds of PBKDF2 (RFC2898) with a cryptographically random salt. 15 | /// The generated key will then be passed into AES-256 (RijndalManaged) which will encrypt the data 16 | /// in cypher block chaining (CBC) mode, and then write both the PBKDF2 salt and encrypted data onto the disk. 17 | /// 18 | public static class FileEncryptor 19 | { 20 | private const int PBKDF2_ITERATIONS = 50000; //Set to 50k to make program not unbearably slow. May increase in future. 21 | private const int SALT_LENGTH = 8; 22 | private const int KEY_SIZE_BYTES = 32; 23 | private const int IV_LENGTH = 16; 24 | 25 | /// 26 | /// Returns an 8-byte cryptographically random salt in base64 encoding 27 | /// 28 | /// 29 | public static string GetRandomSalt() 30 | { 31 | byte[] salt = new byte[SALT_LENGTH]; 32 | using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) 33 | { 34 | rng.GetBytes(salt); 35 | } 36 | return Convert.ToBase64String(salt); 37 | } 38 | 39 | /// 40 | /// Returns a 16-byte cryptographically random initialization vector (IV) in base64 encoding 41 | /// 42 | /// 43 | public static string GetInitializationVector() 44 | { 45 | byte[] IV = new byte[IV_LENGTH]; 46 | using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) 47 | { 48 | rng.GetBytes(IV); 49 | } 50 | return Convert.ToBase64String(IV); 51 | } 52 | 53 | 54 | /// 55 | /// Generates an encryption key derived using a password, a random salt, and specified number of rounds of PBKDF2 56 | /// 57 | /// TODO: pass in password via SecureString? 58 | /// 59 | /// 60 | /// 61 | /// 62 | private static byte[] GetEncryptionKey(string password, string salt) 63 | { 64 | if (string.IsNullOrEmpty(password)) 65 | { 66 | throw new ArgumentException("Password is empty"); 67 | } 68 | if (string.IsNullOrEmpty(salt)) 69 | { 70 | throw new ArgumentException("Salt is empty"); 71 | } 72 | using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, Convert.FromBase64String(salt), PBKDF2_ITERATIONS)) 73 | { 74 | return pbkdf2.GetBytes(KEY_SIZE_BYTES); 75 | } 76 | } 77 | 78 | /// 79 | /// Tries to decrypt and return data given an encrypted base64 encoded string. Must use the same 80 | /// password, salt, IV, and ciphertext that was used during the original encryption of the data. 81 | /// 82 | /// 83 | /// 84 | /// Initialization Vector 85 | /// 86 | /// 87 | public static string DecryptData(string password, string passwordSalt, string IV, string encryptedData) 88 | { 89 | if (string.IsNullOrEmpty(password)) 90 | { 91 | throw new ArgumentException("Password is empty"); 92 | } 93 | if (string.IsNullOrEmpty(passwordSalt)) 94 | { 95 | throw new ArgumentException("Salt is empty"); 96 | } 97 | if (string.IsNullOrEmpty(IV)) 98 | { 99 | throw new ArgumentException("Initialization Vector is empty"); 100 | } 101 | if (string.IsNullOrEmpty(encryptedData)) 102 | { 103 | throw new ArgumentException("Encrypted data is empty"); 104 | } 105 | 106 | byte[] cipherText = Convert.FromBase64String(encryptedData); 107 | byte[] key = GetEncryptionKey(password, passwordSalt); 108 | string plaintext = null; 109 | 110 | using (RijndaelManaged aes256 = new RijndaelManaged()) 111 | { 112 | aes256.IV = Convert.FromBase64String(IV); 113 | aes256.Key = key; 114 | aes256.Padding = PaddingMode.PKCS7; 115 | aes256.Mode = CipherMode.CBC; 116 | 117 | //create decryptor to perform the stream transform 118 | ICryptoTransform decryptor = aes256.CreateDecryptor(aes256.Key, aes256.IV); 119 | 120 | //wrap in a try since a bad password yields a bad key, which would throw an exception on decrypt 121 | try 122 | { 123 | using (MemoryStream msDecrypt = new MemoryStream(cipherText)) 124 | { 125 | using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) 126 | { 127 | using (StreamReader srDecrypt = new StreamReader(csDecrypt)) 128 | { 129 | plaintext = srDecrypt.ReadToEnd(); 130 | } 131 | } 132 | } 133 | } 134 | catch (CryptographicException) 135 | { 136 | plaintext = null; 137 | } 138 | } 139 | return plaintext; 140 | } 141 | 142 | /// 143 | /// Encrypts a string given a password, salt, and initialization vector, then returns result in base64 encoded string. 144 | /// 145 | /// To retrieve this data, you must decrypt with the same password, salt, IV, and cyphertext that was used during encryption 146 | /// 147 | /// 148 | /// 149 | /// 150 | /// 151 | /// 152 | public static string EncryptData(string password, string passwordSalt, string IV, string plaintext) 153 | { 154 | if (string.IsNullOrEmpty(password)) 155 | { 156 | throw new ArgumentException("Password is empty"); 157 | } 158 | if (string.IsNullOrEmpty(passwordSalt)) 159 | { 160 | throw new ArgumentException("Salt is empty"); 161 | } 162 | if (string.IsNullOrEmpty(IV)) 163 | { 164 | throw new ArgumentException("Initialization Vector is empty"); 165 | } 166 | if (string.IsNullOrEmpty(plaintext)) 167 | { 168 | throw new ArgumentException("Plaintext data is empty"); 169 | } 170 | byte[] key = GetEncryptionKey(password, passwordSalt); 171 | byte[] ciphertext; 172 | 173 | using (RijndaelManaged aes256 = new RijndaelManaged()) 174 | { 175 | aes256.Key = key; 176 | aes256.IV = Convert.FromBase64String(IV); 177 | aes256.Padding = PaddingMode.PKCS7; 178 | aes256.Mode = CipherMode.CBC; 179 | 180 | ICryptoTransform encryptor = aes256.CreateEncryptor(aes256.Key, aes256.IV); 181 | 182 | using (MemoryStream msEncrypt = new MemoryStream()) 183 | { 184 | using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 185 | { 186 | using (StreamWriter swEncypt = new StreamWriter(csEncrypt)) 187 | { 188 | swEncypt.Write(plaintext); 189 | } 190 | ciphertext = msEncrypt.ToArray(); 191 | } 192 | } 193 | } 194 | return Convert.ToBase64String(ciphertext); 195 | } 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/ImportAccountForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using SteamAuth; 11 | using Newtonsoft.Json; 12 | using Newtonsoft.Json.Linq; 13 | using System.IO; 14 | 15 | namespace Steam_Desktop_Authenticator 16 | { 17 | public partial class ImportAccountForm : Form 18 | { 19 | private Manifest mManifest; 20 | 21 | public ImportAccountForm() 22 | { 23 | InitializeComponent(); 24 | this.mManifest = Manifest.GetManifest(); 25 | } 26 | 27 | private void btnImport_Click(object sender, EventArgs e) 28 | { 29 | // check if data already added is encripted 30 | #region check if data already added is encripted 31 | string ContiuneImport = "0"; 32 | 33 | string ManifestFile = "maFiles/manifest.json"; 34 | if (File.Exists(ManifestFile)) 35 | { 36 | string AppManifestContents = File.ReadAllText(ManifestFile); 37 | AppManifest AppManifestData = JsonConvert.DeserializeObject(AppManifestContents); 38 | bool AppManifestData_encrypted = AppManifestData.Encrypted; 39 | if (AppManifestData_encrypted == true) 40 | { 41 | MessageBox.Show("You can't import an .maFile because the existing account in the app is encrypted.\nDecrypt it and try again."); 42 | this.Close(); 43 | } 44 | else if (AppManifestData_encrypted == false) 45 | { 46 | ContiuneImport = "1"; 47 | } 48 | else 49 | { 50 | MessageBox.Show("invalid value for variable 'encrypted' inside manifest.json"); 51 | this.Close(); 52 | } 53 | } 54 | else 55 | { 56 | MessageBox.Show("An Error occurred, Restart the program!"); 57 | } 58 | #endregion 59 | 60 | // Continue 61 | #region Continue 62 | if (ContiuneImport == "1") 63 | { 64 | this.Close(); 65 | 66 | // read EncriptionKey from imput box 67 | string ImportUsingEncriptionKey = txtBox.Text; 68 | 69 | // Open file browser > to select the file 70 | OpenFileDialog openFileDialog1 = new OpenFileDialog(); 71 | 72 | // Set filter options and filter index. 73 | openFileDialog1.Filter = "maFiles (.maFile)|*.maFile|All Files (*.*)|*.*"; 74 | openFileDialog1.FilterIndex = 1; 75 | openFileDialog1.Multiselect = false; 76 | 77 | // Call the ShowDialog method to show the dialog box. 78 | DialogResult userClickedOK = openFileDialog1.ShowDialog(); 79 | 80 | // Process input if the user clicked OK. 81 | if (userClickedOK == DialogResult.OK) 82 | { 83 | // Open the selected file to read. 84 | System.IO.Stream fileStream = openFileDialog1.OpenFile(); 85 | string fileContents = null; 86 | 87 | using (System.IO.StreamReader reader = new System.IO.StreamReader(fileStream)) 88 | { 89 | fileContents = reader.ReadToEnd(); 90 | } 91 | fileStream.Close(); 92 | 93 | try 94 | { 95 | if (ImportUsingEncriptionKey == "") 96 | { 97 | // Import maFile 98 | //------------------------------------------- 99 | #region Import maFile 100 | SteamGuardAccount maFile = JsonConvert.DeserializeObject(fileContents); 101 | if (maFile.Session.SteamID != 0) 102 | { 103 | mManifest.SaveAccount(maFile, false); 104 | MessageBox.Show("Account Imported!"); 105 | } 106 | else 107 | { 108 | throw new Exception("Invalid SteamID"); 109 | } 110 | #endregion 111 | } 112 | else 113 | { 114 | // Import Encripted maFile 115 | //------------------------------------------- 116 | #region Import Encripted maFile 117 | //Read manifest.json encryption_iv encryption_salt 118 | string ImportFileName_Found = "0"; 119 | string Salt_Found = null; 120 | string IV_Found = null; 121 | string ReadManifestEx = "0"; 122 | 123 | //No directory means no manifest file anyways. 124 | ImportManifest newImportManifest = new ImportManifest(); 125 | newImportManifest.Encrypted = false; 126 | newImportManifest.Entries = new List(); 127 | 128 | // extract folder path 129 | string fullPath = openFileDialog1.FileName; 130 | string fileName = openFileDialog1.SafeFileName; 131 | string path = fullPath.Replace(fileName, ""); 132 | 133 | // extract fileName 134 | string ImportFileName = fullPath.Replace(path, ""); 135 | 136 | string ImportManifestFile = path + "manifest.json"; 137 | 138 | 139 | if (File.Exists(ImportManifestFile)) 140 | { 141 | string ImportManifestContents = File.ReadAllText(ImportManifestFile); 142 | 143 | 144 | try 145 | { 146 | ImportManifest account = JsonConvert.DeserializeObject(ImportManifestContents); 147 | //bool Import_encrypted = account.Encrypted; 148 | 149 | List newEntries = new List(); 150 | 151 | foreach (var entry in account.Entries) 152 | { 153 | string FileName = entry.Filename; 154 | string encryption_iv = entry.IV; 155 | string encryption_salt = entry.Salt; 156 | 157 | if (ImportFileName == FileName) 158 | { 159 | ImportFileName_Found = "1"; 160 | IV_Found = entry.IV; 161 | Salt_Found = entry.Salt; 162 | } 163 | } 164 | } 165 | catch (Exception) 166 | { 167 | ReadManifestEx = "1"; 168 | MessageBox.Show("Invalid content inside manifest.json!\nImport Failed."); 169 | } 170 | 171 | 172 | // DECRIPT & Import 173 | //-------------------- 174 | #region DECRIPT & Import 175 | if (ReadManifestEx == "0") 176 | { 177 | if (ImportFileName_Found == "1" && Salt_Found != null && IV_Found != null) 178 | { 179 | string decryptedText = FileEncryptor.DecryptData(ImportUsingEncriptionKey, Salt_Found, IV_Found, fileContents); 180 | 181 | if (decryptedText == null) 182 | { 183 | MessageBox.Show("Decryption Failed.\nImport Failed."); 184 | } 185 | else 186 | { 187 | string fileText = decryptedText; 188 | 189 | SteamGuardAccount maFile = JsonConvert.DeserializeObject(fileText); 190 | if (maFile.Session.SteamID != 0) 191 | { 192 | mManifest.SaveAccount(maFile, false); 193 | MessageBox.Show("Account Imported!\nYour Account in now Decrypted!"); 194 | //MainForm.loadAccountsList(); 195 | } 196 | else 197 | { 198 | MessageBox.Show("Invalid SteamID.\nImport Failed."); 199 | } 200 | } 201 | } 202 | else 203 | { 204 | if (ImportFileName_Found == "0") 205 | { 206 | MessageBox.Show("Account not found inside manifest.json.\nImport Failed."); 207 | } 208 | else if (Salt_Found == null && IV_Found == null) 209 | { 210 | MessageBox.Show("manifest.json does not contain encrypted data.\nYour account may be unencrypted!\nImport Failed."); 211 | } 212 | else 213 | { 214 | if (IV_Found == null) 215 | { 216 | MessageBox.Show("manifest.json does not contain: encryption_iv\nImport Failed."); 217 | } 218 | else if (IV_Found == null) 219 | { 220 | MessageBox.Show("manifest.json does not contain: encryption_salt\nImport Failed."); 221 | } 222 | } 223 | } 224 | } 225 | #endregion //DECRIPT & Import END 226 | 227 | 228 | } 229 | else 230 | { 231 | MessageBox.Show("manifest.json is missing!\nImport Failed."); 232 | } 233 | #endregion //Import Encripted maFile END 234 | } 235 | 236 | } 237 | catch (Exception) 238 | { 239 | MessageBox.Show("This file is not a valid SteamAuth maFile.\nImport Failed."); 240 | } 241 | } 242 | } 243 | #endregion // Continue End 244 | } 245 | 246 | private void btnCancel_Click(object sender, EventArgs e) 247 | { 248 | this.Close(); 249 | } 250 | 251 | private void Import_maFile_Form_FormClosing(object sender, FormClosingEventArgs e) 252 | { 253 | } 254 | } 255 | 256 | 257 | public class AppManifest 258 | { 259 | [JsonProperty("encrypted")] 260 | public bool Encrypted { get; set; } 261 | } 262 | 263 | 264 | public class ImportManifest 265 | { 266 | [JsonProperty("encrypted")] 267 | public bool Encrypted { get; set; } 268 | 269 | [JsonProperty("entries")] 270 | public List Entries { get; set; } 271 | } 272 | 273 | public class ImportManifestEntry 274 | { 275 | [JsonProperty("encryption_iv")] 276 | public string IV { get; set; } 277 | 278 | [JsonProperty("encryption_salt")] 279 | public string Salt { get; set; } 280 | 281 | [JsonProperty("filename")] 282 | public string Filename { get; set; } 283 | 284 | [JsonProperty("steamid")] 285 | public ulong SteamID { get; set; } 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/Steam Desktop Authenticator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Debug 10 | AnyCPU 11 | {0F37C513-9AF4-42C8-9CE9-F9B3BFA55E4E} 12 | WinExe 13 | Properties 14 | Steam_Desktop_Authenticator 15 | Steam Desktop Authenticator 16 | v4.6.2 17 | 512 18 | true 19 | false 20 | 21 | 22 | 23 | publish\ 24 | true 25 | Disk 26 | false 27 | Foreground 28 | 7 29 | Days 30 | false 31 | false 32 | true 33 | 0 34 | 0.2.2.%2a 35 | false 36 | true 37 | 38 | 39 | false 40 | 41 | 42 | 43 | 44 | 45 | 46 | true 47 | bin\x64\Debug\ 48 | DEBUG;TRACE 49 | full 50 | x64 51 | prompt 52 | MinimumRecommendedRules.ruleset 53 | true 54 | 55 | 56 | bin\x64\Release\ 57 | 58 | 59 | true 60 | none 61 | x64 62 | prompt 63 | MinimumRecommendedRules.ruleset 64 | true 65 | 66 | 67 | true 68 | bin\Debug\ 69 | 70 | 71 | full 72 | x86 73 | prompt 74 | MinimumRecommendedRules.ruleset 75 | true 76 | Auto 77 | 78 | 79 | bin\Release\ 80 | 81 | 82 | true 83 | pdbonly 84 | x86 85 | prompt 86 | MinimumRecommendedRules.ruleset 87 | true 88 | Auto 89 | true 90 | false 91 | 92 | 93 | icon.ico 94 | 95 | 96 | 97 | packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll 98 | 99 | 100 | packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | Form 118 | 119 | 120 | ConfirmationFormWeb.cs 121 | 122 | 123 | 124 | 125 | Form 126 | 127 | 128 | CaptchaForm.cs 129 | 130 | 131 | Form 132 | 133 | 134 | ImportAccountForm.cs 135 | 136 | 137 | Form 138 | 139 | 140 | InputForm.cs 141 | 142 | 143 | Form 144 | 145 | 146 | InstallRedistribForm.cs 147 | 148 | 149 | Form 150 | 151 | 152 | ListInputForm.cs 153 | 154 | 155 | Form 156 | 157 | 158 | LoginForm.cs 159 | 160 | 161 | 162 | Form 163 | 164 | 165 | MainForm.cs 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | Form 175 | 176 | 177 | SettingsForm.cs 178 | 179 | 180 | Form 181 | 182 | 183 | TradePopupForm.cs 184 | 185 | 186 | Form 187 | 188 | 189 | WelcomeForm.cs 190 | 191 | 192 | CaptchaForm.cs 193 | 194 | 195 | ConfirmationFormWeb.cs 196 | 197 | 198 | ImportAccountForm.cs 199 | 200 | 201 | InputForm.cs 202 | 203 | 204 | InstallRedistribForm.cs 205 | 206 | 207 | ListInputForm.cs 208 | 209 | 210 | LoginForm.cs 211 | 212 | 213 | MainForm.cs 214 | 215 | 216 | SettingsForm.cs 217 | 218 | 219 | TradePopupForm.cs 220 | 221 | 222 | WelcomeForm.cs 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | {5ad0934e-f6c4-4ae5-83af-c788313b2a87} 232 | SteamAuth 233 | 234 | 235 | 236 | 237 | False 238 | Microsoft .NET Framework 4.5.2 %28x86 and x64%29 239 | true 240 | 241 | 242 | False 243 | .NET Framework 3.5 SP1 244 | false 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 271 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/PhoneBridge.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SteamAuth; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | using System.IO; 11 | using System.Text.RegularExpressions; 12 | 13 | namespace Steam_Desktop_Authenticator 14 | { 15 | public class PhoneBridge 16 | { 17 | public bool OutputToConsole = true; 18 | public bool OutputToLog = true; 19 | 20 | private Process console; 21 | private ManualResetEvent mreOutput = new ManualResetEvent(false); 22 | 23 | public delegate void BridgeOutput(string msg); 24 | public event BridgeOutput PhoneBridgeError; 25 | public event BridgeOutput OutputLog; 26 | private void OnPhoneBridgeError(string msg) 27 | { 28 | if (PhoneBridgeError != null) 29 | PhoneBridgeError(msg); 30 | } 31 | private void OnOutputLog(string msg) 32 | { 33 | if (OutputLog != null) 34 | OutputLog(msg); 35 | if (OutputToLog) 36 | AppendToLog(msg); 37 | } 38 | 39 | private string Error = ""; 40 | 41 | private void InitConsole() 42 | { 43 | if (console != null) return; 44 | 45 | console = new Process(); 46 | 47 | console.StartInfo.UseShellExecute = false; 48 | console.StartInfo.RedirectStandardOutput = true; 49 | console.StartInfo.RedirectStandardInput = true; 50 | console.StartInfo.CreateNoWindow = true; 51 | console.StartInfo.FileName = "CMD.exe"; 52 | console.StartInfo.Arguments = "/K"; 53 | console.Start(); 54 | console.BeginOutputReadLine(); 55 | 56 | console.OutputDataReceived += (sender, e) => 57 | { 58 | if (e?.Data == null || e.Data.Contains(">@") || !OutputToConsole || e.Data == "") return; 59 | if (OutputToConsole) 60 | Console.WriteLine(e.Data); 61 | if (OutputToLog) 62 | AppendToLog(e.Data); 63 | }; 64 | } 65 | 66 | private void AppendToLog(string line) 67 | { 68 | StreamWriter s = File.AppendText("adblog.txt"); 69 | s.WriteLine(line); 70 | s.Flush(); 71 | s.Close(); 72 | } 73 | 74 | public SteamGuardAccount ExtractSteamGuardAccount(string id = "*", bool skipChecks = false) 75 | { 76 | if (!skipChecks) AppendToLog(""); 77 | InitConsole(); // Init the console 78 | 79 | if (!skipChecks) 80 | { 81 | OnOutputLog("Checking requirements..."); 82 | // Check required states 83 | Error = ErrorsFound(); 84 | if (Error != "") 85 | { 86 | OnPhoneBridgeError(Error); 87 | return null; 88 | } 89 | } 90 | 91 | bool root = IsRooted(); 92 | 93 | //root = false; // DEBUG /////////////////////// 94 | 95 | SteamGuardAccount acc; 96 | string json; 97 | 98 | if (root) 99 | { 100 | OnOutputLog("Using root method"); 101 | json = PullJson(id); 102 | } 103 | else 104 | { 105 | OnOutputLog("Steam has blocked the non-root method of copying data from their app."); 106 | OnOutputLog("Your phone must now be rooted to use this."); 107 | json = null; 108 | //json = PullJsonNoRoot(id); 109 | } 110 | 111 | if (json == null) 112 | return null; 113 | acc = JsonConvert.DeserializeObject(json, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore }); 114 | acc.DeviceID = GetDeviceID(root); 115 | 116 | if (acc.DeviceID == null) 117 | { 118 | try 119 | { 120 | OnPhoneBridgeError("failed to read the UUID (device id)"); 121 | } 122 | catch (Exception) { } 123 | } 124 | 125 | return acc; 126 | } 127 | 128 | private string ErrorsFound() 129 | { 130 | if (!CheckAdb()) return "ADB not found"; 131 | if (!DeviceUp()) return "Device not detected"; 132 | if (!SteamAppInstalled()) return "Steam Community app not installed"; 133 | return ""; 134 | } 135 | 136 | private string GetDeviceID(bool root) 137 | { 138 | OnOutputLog("Extracting Device ID"); 139 | string id = null; 140 | ManualResetEventSlim mre = new ManualResetEventSlim(); 141 | DataReceivedEventHandler f1 = (sender, e) => 142 | { 143 | if (e.Data.Contains(">@") || e.Data == "") return; 144 | 145 | Regex rx = new Regex(@"]*\s+name=" + "\"uuidKey\"" + @"[^>]*>[\s\t\r\n]*(android:.+)[\s\t\r\n]*<\/string>", RegexOptions.IgnoreCase); 146 | Match m = rx.Match(e.Data); 147 | if (m.Success) { id = m.Groups[1].Value; } 148 | 149 | //this need more test,but also is not necessary 150 | //if (e.Data.TrimEnd(' ', '\t', '\n', '\r').EndsWith("Done")) 151 | mre.Set(); 152 | }; 153 | 154 | console.OutputDataReceived += f1; 155 | 156 | if (root) 157 | ExecuteCommand($"adb shell su -c 'sed -n 3p /data/data/$STEAMAPP/shared_prefs/steam.uuid.xml' & echo Done"); 158 | else 159 | ExecuteCommand("adb shell \"cat /sdcard/steamauth/apps/$STEAMAPP/sp/steam.uuid.xml\" & echo Done"); 160 | mre.Wait(); 161 | 162 | console.OutputDataReceived -= f1; 163 | 164 | CleanBackup(); 165 | 166 | return id; 167 | } 168 | 169 | private string PullJson(string id = "*") 170 | { 171 | string steamid = id; 172 | string json = null; 173 | int count = 0; 174 | List accs = new List(); 175 | ManualResetEventSlim mre = new ManualResetEventSlim(); 176 | 177 | DataReceivedEventHandler f1 = (sender, e) => 178 | { 179 | if (e.Data.Contains(">@") || e.Data == "") return; 180 | if (e.Data.Contains("No such file or directory")) 181 | { 182 | mre.Set(); 183 | return; 184 | } 185 | 186 | if (e.Data.Contains("Steamguard-")) 187 | { 188 | steamid = e.Data.Split('-')[1]; 189 | accs.Add(steamid); 190 | count++; 191 | } 192 | 193 | if (e.Data == "Done") 194 | mre.Set(); 195 | 196 | if (e.Data.StartsWith("{")) 197 | { 198 | json = e.Data; 199 | mre.Set(); 200 | } 201 | }; 202 | 203 | console.OutputDataReceived += f1; 204 | 205 | if (steamid == "*") 206 | { 207 | OnOutputLog("Extracting (1/2)"); 208 | ExecuteCommand("adb shell \"su -c 'ls /data/data/com.valvesoftware.android.steam.community/files'\" & echo Done"); 209 | mre.Wait(); 210 | if (count > 1) 211 | { 212 | OnMoreThanOneAccount(accs); 213 | return null; 214 | } 215 | } 216 | 217 | mre.Reset(); 218 | OnOutputLog("Extracting " + steamid + " (2/2)"); 219 | ExecuteCommand("adb shell \"su -c 'cat /data/data/com.valvesoftware.android.steam.community/files/Steamguard-" + steamid + "'\""); 220 | mre.Wait(); 221 | 222 | console.OutputDataReceived -= f1; 223 | 224 | if (json == null) 225 | { 226 | OnOutputLog("An error occured while extracting files"); 227 | } 228 | 229 | return json; 230 | } 231 | 232 | private string PullJsonNoRoot(string id = "*") 233 | { 234 | string json = "Error"; 235 | string sid = id; 236 | ManualResetEventSlim mre = new ManualResetEventSlim(); 237 | DataReceivedEventHandler f1 = (sender, e) => 238 | { 239 | if (e.Data.Contains(">@") || e.Data == "") return; 240 | if (e.Data == "Done") 241 | mre.Set(); 242 | if (e.Data.StartsWith("{")) 243 | json = e.Data; 244 | }; 245 | 246 | console.OutputDataReceived += f1; 247 | 248 | if (!Directory.Exists("steamguard")) 249 | { 250 | DoBackup(); 251 | } 252 | 253 | mre.Reset(); 254 | OnOutputLog("Extracting (4/5)"); 255 | ExecuteCommand("adb pull /sdcard/steamauth/apps/$STEAMAPP/f steamguard/ & echo Done"); 256 | mre.Wait(); 257 | 258 | mre.Reset(); 259 | OnOutputLog("Extracting (5/5)"); 260 | ExecuteCommand("adb shell \"rm -dR /sdcard/steamauth\" & echo Done"); 261 | mre.Wait(); 262 | 263 | string[] files = Directory.EnumerateFiles("steamguard").ToArray(); 264 | for (int i = 0; i < files.Length; i++) 265 | { 266 | files[i] = files[i].Split('-')[1]; 267 | } 268 | 269 | if (files.Length > 1 && sid == "*") 270 | { 271 | OnMoreThanOneAccount(new List(files)); 272 | return null; 273 | } 274 | else 275 | { 276 | json = File.ReadAllText("steamguard/Steamguard-" + sid); 277 | } 278 | 279 | console.OutputDataReceived -= f1; 280 | 281 | return json; 282 | } 283 | 284 | private void CleanBackup() 285 | { 286 | File.Delete("backup.ab"); 287 | if (Directory.Exists("steamguard")) 288 | Directory.Delete("steamguard", true); 289 | } 290 | 291 | private void DoBackup() 292 | { 293 | ManualResetEventSlim mre = new ManualResetEventSlim(); 294 | DataReceivedEventHandler f1 = (sender, e) => 295 | { 296 | if (e.Data.Contains(">@") || e.Data == "") return; 297 | if (e.Data == "Done") 298 | mre.Set(); 299 | }; 300 | 301 | console.OutputDataReceived += f1; 302 | 303 | OnOutputLog("Extracting (1/5)"); 304 | ExecuteCommand("adb backup --noapk com.valvesoftware.android.steam.community & echo Done"); 305 | OnOutputLog("Now unlock your phone and confirm operation"); 306 | mre.Wait(); 307 | 308 | mre.Reset(); 309 | OnOutputLog("Extracting (2/5)"); 310 | ExecuteCommand("adb push backup.ab /sdcard/steamauth/backup.ab & echo Done"); 311 | mre.Wait(); 312 | 313 | mre.Reset(); 314 | OnOutputLog("Extracting (3/5)"); 315 | ExecuteCommand("adb shell \" cd /sdcard/steamauth ; ( printf " + @" '\x1f\x8b\x08\x00\x00\x00\x00\x00'" + " ; tail -c +25 backup.ab ) | tar xfvz - \" & echo Done"); 316 | mre.Wait(); 317 | 318 | console.OutputDataReceived -= f1; 319 | } 320 | 321 | private bool CheckAdb() 322 | { 323 | bool exists = true; 324 | Process p = new Process(); 325 | 326 | OnOutputLog("Checking for ADB"); 327 | 328 | p.StartInfo.FileName = "adb.exe"; 329 | p.StartInfo.CreateNoWindow = true; 330 | p.StartInfo.UseShellExecute = false; 331 | 332 | try 333 | { 334 | p.Start(); 335 | } 336 | catch (Exception) 337 | { 338 | exists = false; 339 | } 340 | 341 | return exists; 342 | } 343 | 344 | private bool DeviceUp() 345 | { 346 | OnOutputLog("Checking for device"); 347 | bool up = false; 348 | 349 | up = GetState() == "device"; 350 | 351 | return up; 352 | } 353 | 354 | private bool SteamAppInstalled() 355 | { 356 | OnOutputLog("Checking for Steam app"); 357 | bool ins = false; 358 | ManualResetEventSlim mre = new ManualResetEventSlim(); 359 | DataReceivedEventHandler f1 = (sender, e) => 360 | { 361 | if (e.Data.Contains(">@") || e.Data == "") return; 362 | if (e.Data == "Yes") 363 | ins = true; 364 | mre.Set(); 365 | }; 366 | 367 | console.OutputDataReceived += f1; 368 | 369 | ExecuteCommand("adb shell \"su -c 'cd /data/data/com.valvesoftware.android.steam.community && echo Yes'\""); 370 | mre.Wait(); 371 | 372 | console.OutputDataReceived -= f1; 373 | 374 | return ins; 375 | } 376 | 377 | private bool IsRooted() 378 | { 379 | OnOutputLog("Checking root"); 380 | bool root = false; 381 | ManualResetEventSlim mre = new ManualResetEventSlim(); 382 | DataReceivedEventHandler f1 = (sender, e) => 383 | { 384 | if (e.Data.Contains(">@") || e.Data == "") return; 385 | if (e.Data.Contains("Yes")) 386 | root = true; 387 | mre.Set(); 388 | }; 389 | 390 | console.OutputDataReceived += f1; 391 | 392 | ExecuteCommand("adb shell su -c 'echo Yes'"); 393 | mre.Wait(); 394 | 395 | console.OutputDataReceived -= f1; 396 | 397 | return root; 398 | } 399 | 400 | 401 | public delegate void AccountsDelegate(List accounts); 402 | public event AccountsDelegate MoreThanOneAccount; 403 | private void OnMoreThanOneAccount(List accounts) 404 | { 405 | if (MoreThanOneAccount != null) 406 | MoreThanOneAccount(accounts); 407 | } 408 | 409 | 410 | public event EventHandler DeviceWaited; 411 | protected void OnDeviceWaited() 412 | { 413 | if (DeviceWaited != null) 414 | { 415 | DeviceWaited(this, EventArgs.Empty); 416 | } 417 | } 418 | 419 | public void WaitForDeviceAsync() 420 | { 421 | InitConsole(); 422 | console.OutputDataReceived += WaitForDeviceCallback; 423 | 424 | ExecuteCommand("adb wait-for-device & echo Done"); 425 | } 426 | 427 | private void WaitForDeviceCallback(object sender, DataReceivedEventArgs e) 428 | { 429 | if (e.Data.Contains(">@") || e.Data == "") return; 430 | if (e.Data == "Done") 431 | OnDeviceWaited(); 432 | } 433 | 434 | public string GetState() 435 | { 436 | InitConsole(); 437 | if (!CheckAdb()) return "noadb"; 438 | 439 | string state = "Error"; 440 | ManualResetEventSlim mre = new ManualResetEventSlim(); 441 | DataReceivedEventHandler f1 = (sender, e) => 442 | { 443 | if (e.Data.Contains(">@") || e.Data == "") return; 444 | state = e.Data; 445 | mre.Set(); 446 | }; 447 | 448 | console.OutputDataReceived += f1; 449 | 450 | ExecuteCommand("adb get-state"); 451 | mre.Wait(); 452 | 453 | console.OutputDataReceived -= f1; 454 | 455 | return state; 456 | } 457 | 458 | public void ConnectWiFi(string ip) 459 | { 460 | InitConsole(); 461 | ExecuteCommand("adb connect " + ip); 462 | } 463 | 464 | private void ExecuteCommand(string cmd) 465 | { 466 | console.StandardInput.WriteLine("@" + cmd.Replace("$STEAMAPP", "com.valvesoftware.android.steam.community")); 467 | console.StandardInput.Flush(); 468 | } 469 | 470 | public void Close() 471 | { 472 | console.Close(); 473 | console.WaitForExit(); 474 | } 475 | } 476 | } 477 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/LoginForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using SteamAuth; 4 | 5 | namespace Steam_Desktop_Authenticator 6 | { 7 | public partial class LoginForm : Form 8 | { 9 | public SteamGuardAccount account; 10 | public LoginType LoginReason; 11 | 12 | public LoginForm(LoginType loginReason = LoginType.Initial, SteamGuardAccount account = null) 13 | { 14 | InitializeComponent(); 15 | this.LoginReason = loginReason; 16 | this.account = account; 17 | 18 | try 19 | { 20 | if (this.LoginReason != LoginType.Initial) 21 | { 22 | txtUsername.Text = account.AccountName; 23 | txtUsername.Enabled = false; 24 | } 25 | 26 | if (this.LoginReason == LoginType.Refresh) 27 | { 28 | labelLoginExplanation.Text = "Your Steam credentials have expired. For trade and market confirmations to work properly, please login again."; 29 | } 30 | } 31 | catch (Exception) 32 | { 33 | MessageBox.Show("Failed to find your account. Try closing and re-opening SDA.", "Login Failed", MessageBoxButtons.OK, MessageBoxIcon.Error); 34 | this.Close(); 35 | } 36 | } 37 | 38 | public void SetUsername(string username) 39 | { 40 | txtUsername.Text = username; 41 | } 42 | 43 | public string FilterPhoneNumber(string phoneNumber) 44 | { 45 | return phoneNumber.Replace("-", "").Replace("(", "").Replace(")", ""); 46 | } 47 | 48 | public bool PhoneNumberOkay(string phoneNumber) 49 | { 50 | if (phoneNumber == null || phoneNumber.Length == 0) return false; 51 | if (phoneNumber[0] != '+') return false; 52 | return true; 53 | } 54 | 55 | private void btnSteamLogin_Click(object sender, EventArgs e) 56 | { 57 | string username = txtUsername.Text; 58 | string password = txtPassword.Text; 59 | 60 | if (LoginReason == LoginType.Refresh) 61 | { 62 | RefreshLogin(username, password); 63 | return; 64 | } 65 | 66 | var userLogin = new UserLogin(username, password); 67 | LoginResult response = LoginResult.BadCredentials; 68 | 69 | while ((response = userLogin.DoLogin()) != LoginResult.LoginOkay) 70 | { 71 | switch (response) 72 | { 73 | case LoginResult.NeedEmail: 74 | InputForm emailForm = new InputForm("Enter the code sent to your email:"); 75 | emailForm.ShowDialog(); 76 | if (emailForm.Canceled) 77 | { 78 | this.Close(); 79 | return; 80 | } 81 | 82 | userLogin.EmailCode = emailForm.txtBox.Text; 83 | break; 84 | 85 | case LoginResult.NeedCaptcha: 86 | CaptchaForm captchaForm = new CaptchaForm(userLogin.CaptchaGID); 87 | captchaForm.ShowDialog(); 88 | if (captchaForm.Canceled) 89 | { 90 | this.Close(); 91 | return; 92 | } 93 | 94 | userLogin.CaptchaText = captchaForm.CaptchaCode; 95 | break; 96 | 97 | case LoginResult.Need2FA: 98 | MessageBox.Show("This account already has a mobile authenticator linked to it.\nRemove the old authenticator from your Steam account before adding a new one.", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 99 | this.Close(); 100 | return; 101 | 102 | case LoginResult.BadRSA: 103 | MessageBox.Show("Error logging in: Steam returned \"BadRSA\".", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 104 | this.Close(); 105 | return; 106 | 107 | case LoginResult.BadCredentials: 108 | MessageBox.Show("Error logging in: Username or password was incorrect.", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 109 | this.Close(); 110 | return; 111 | 112 | case LoginResult.TooManyFailedLogins: 113 | MessageBox.Show("Error logging in: Too many failed logins, try again later.", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 114 | this.Close(); 115 | return; 116 | 117 | case LoginResult.GeneralFailure: 118 | MessageBox.Show("Error logging in: Steam returned \"GeneralFailure\".", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 119 | this.Close(); 120 | return; 121 | } 122 | } 123 | 124 | //Login succeeded 125 | 126 | SessionData session = userLogin.Session; 127 | AuthenticatorLinker linker = new AuthenticatorLinker(session); 128 | 129 | AuthenticatorLinker.LinkResult linkResponse = AuthenticatorLinker.LinkResult.GeneralFailure; 130 | 131 | while ((linkResponse = linker.AddAuthenticator()) != AuthenticatorLinker.LinkResult.AwaitingFinalization) 132 | { 133 | switch (linkResponse) 134 | { 135 | case AuthenticatorLinker.LinkResult.MustProvidePhoneNumber: 136 | string phoneNumber = ""; 137 | while (!PhoneNumberOkay(phoneNumber)) 138 | { 139 | InputForm phoneNumberForm = new InputForm("Enter your phone number in the following format: +{cC} phoneNumber. EG, +1 123-456-7890"); 140 | phoneNumberForm.txtBox.Text = "+1 "; 141 | phoneNumberForm.ShowDialog(); 142 | if (phoneNumberForm.Canceled) 143 | { 144 | this.Close(); 145 | return; 146 | } 147 | 148 | phoneNumber = FilterPhoneNumber(phoneNumberForm.txtBox.Text); 149 | } 150 | linker.PhoneNumber = phoneNumber; 151 | break; 152 | 153 | case AuthenticatorLinker.LinkResult.MustRemovePhoneNumber: 154 | linker.PhoneNumber = null; 155 | break; 156 | 157 | case AuthenticatorLinker.LinkResult.MustConfirmEmail: 158 | MessageBox.Show("Please check your email, and click the link Steam sent you before continuing."); 159 | break; 160 | 161 | case AuthenticatorLinker.LinkResult.GeneralFailure: 162 | MessageBox.Show("Error adding your phone number. Steam returned \"GeneralFailure\"."); 163 | this.Close(); 164 | return; 165 | } 166 | } 167 | 168 | Manifest manifest = Manifest.GetManifest(); 169 | string passKey = null; 170 | if (manifest.Entries.Count == 0) 171 | { 172 | passKey = manifest.PromptSetupPassKey("Please enter an encryption passkey. Leave blank or hit cancel to not encrypt (VERY INSECURE)."); 173 | } 174 | else if (manifest.Entries.Count > 0 && manifest.Encrypted) 175 | { 176 | bool passKeyValid = false; 177 | while (!passKeyValid) 178 | { 179 | InputForm passKeyForm = new InputForm("Please enter your current encryption passkey."); 180 | passKeyForm.ShowDialog(); 181 | if (!passKeyForm.Canceled) 182 | { 183 | passKey = passKeyForm.txtBox.Text; 184 | passKeyValid = manifest.VerifyPasskey(passKey); 185 | if (!passKeyValid) 186 | { 187 | MessageBox.Show("That passkey is invalid. Please enter the same passkey you used for your other accounts."); 188 | } 189 | } 190 | else 191 | { 192 | this.Close(); 193 | return; 194 | } 195 | } 196 | } 197 | 198 | //Save the file immediately; losing this would be bad. 199 | if (!manifest.SaveAccount(linker.LinkedAccount, passKey != null, passKey)) 200 | { 201 | manifest.RemoveAccount(linker.LinkedAccount); 202 | MessageBox.Show("Unable to save mobile authenticator file. The mobile authenticator has not been linked."); 203 | this.Close(); 204 | return; 205 | } 206 | 207 | MessageBox.Show("The Mobile Authenticator has not yet been linked. Before finalizing the authenticator, please write down your revocation code: " + linker.LinkedAccount.RevocationCode); 208 | 209 | AuthenticatorLinker.FinalizeResult finalizeResponse = AuthenticatorLinker.FinalizeResult.GeneralFailure; 210 | while (finalizeResponse != AuthenticatorLinker.FinalizeResult.Success) 211 | { 212 | InputForm smsCodeForm = new InputForm("Please input the SMS code sent to your phone."); 213 | smsCodeForm.ShowDialog(); 214 | if (smsCodeForm.Canceled) 215 | { 216 | manifest.RemoveAccount(linker.LinkedAccount); 217 | this.Close(); 218 | return; 219 | } 220 | 221 | InputForm confirmRevocationCode = new InputForm("Please enter your revocation code to ensure you've saved it."); 222 | confirmRevocationCode.ShowDialog(); 223 | if (confirmRevocationCode.txtBox.Text.ToUpper() != linker.LinkedAccount.RevocationCode) 224 | { 225 | MessageBox.Show("Revocation code incorrect; the authenticator has not been linked."); 226 | manifest.RemoveAccount(linker.LinkedAccount); 227 | this.Close(); 228 | return; 229 | } 230 | 231 | string smsCode = smsCodeForm.txtBox.Text; 232 | finalizeResponse = linker.FinalizeAddAuthenticator(smsCode); 233 | 234 | switch (finalizeResponse) 235 | { 236 | case AuthenticatorLinker.FinalizeResult.BadSMSCode: 237 | continue; 238 | 239 | case AuthenticatorLinker.FinalizeResult.UnableToGenerateCorrectCodes: 240 | MessageBox.Show("Unable to generate the proper codes to finalize this authenticator. The authenticator should not have been linked. In the off-chance it was, please write down your revocation code, as this is the last chance to see it: " + linker.LinkedAccount.RevocationCode); 241 | manifest.RemoveAccount(linker.LinkedAccount); 242 | this.Close(); 243 | return; 244 | 245 | case AuthenticatorLinker.FinalizeResult.GeneralFailure: 246 | MessageBox.Show("Unable to finalize this authenticator. The authenticator should not have been linked. In the off-chance it was, please write down your revocation code, as this is the last chance to see it: " + linker.LinkedAccount.RevocationCode); 247 | manifest.RemoveAccount(linker.LinkedAccount); 248 | this.Close(); 249 | return; 250 | } 251 | } 252 | 253 | //Linked, finally. Re-save with FullyEnrolled property. 254 | manifest.SaveAccount(linker.LinkedAccount, passKey != null, passKey); 255 | MessageBox.Show("Mobile authenticator successfully linked. Please write down your revocation code: " + linker.LinkedAccount.RevocationCode); 256 | this.Close(); 257 | } 258 | 259 | /// 260 | /// Handles logging in to refresh session data. i.e. changing steam password. 261 | /// 262 | /// Steam username 263 | /// Steam password 264 | private async void RefreshLogin(string username, string password) 265 | { 266 | long steamTime = await TimeAligner.GetSteamTimeAsync(); 267 | Manifest man = Manifest.GetManifest(); 268 | 269 | account.FullyEnrolled = true; 270 | 271 | UserLogin mUserLogin = new UserLogin(username, password); 272 | LoginResult response = LoginResult.BadCredentials; 273 | 274 | while ((response = mUserLogin.DoLogin()) != LoginResult.LoginOkay) 275 | { 276 | switch (response) 277 | { 278 | case LoginResult.NeedCaptcha: 279 | CaptchaForm captchaForm = new CaptchaForm(mUserLogin.CaptchaGID); 280 | captchaForm.ShowDialog(); 281 | if (captchaForm.Canceled) 282 | { 283 | this.Close(); 284 | return; 285 | } 286 | 287 | mUserLogin.CaptchaText = captchaForm.CaptchaCode; 288 | break; 289 | 290 | case LoginResult.Need2FA: 291 | mUserLogin.TwoFactorCode = account.GenerateSteamGuardCodeForTime(steamTime); 292 | break; 293 | 294 | case LoginResult.BadRSA: 295 | MessageBox.Show("Error logging in: Steam returned \"BadRSA\".", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 296 | this.Close(); 297 | return; 298 | 299 | case LoginResult.BadCredentials: 300 | MessageBox.Show("Error logging in: Username or password was incorrect.", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 301 | this.Close(); 302 | return; 303 | 304 | case LoginResult.TooManyFailedLogins: 305 | MessageBox.Show("Error logging in: Too many failed logins, try again later.", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 306 | this.Close(); 307 | return; 308 | 309 | case LoginResult.GeneralFailure: 310 | MessageBox.Show("Error logging in: Steam returned \"GeneralFailure\".", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 311 | this.Close(); 312 | return; 313 | } 314 | } 315 | 316 | account.Session = mUserLogin.Session; 317 | 318 | HandleManifest(man, true); 319 | } 320 | 321 | private void HandleManifest(Manifest man, bool IsRefreshing = false) 322 | { 323 | string passKey = null; 324 | if (man.Entries.Count == 0) 325 | { 326 | passKey = man.PromptSetupPassKey("Please enter an encryption passkey. Leave blank or hit cancel to not encrypt (VERY INSECURE)."); 327 | } 328 | else if (man.Entries.Count > 0 && man.Encrypted) 329 | { 330 | bool passKeyValid = false; 331 | while (!passKeyValid) 332 | { 333 | InputForm passKeyForm = new InputForm("Please enter your current encryption passkey."); 334 | passKeyForm.ShowDialog(); 335 | if (!passKeyForm.Canceled) 336 | { 337 | passKey = passKeyForm.txtBox.Text; 338 | passKeyValid = man.VerifyPasskey(passKey); 339 | if (!passKeyValid) 340 | { 341 | MessageBox.Show("That passkey is invalid. Please enter the same passkey you used for your other accounts."); 342 | } 343 | } 344 | else 345 | { 346 | this.Close(); 347 | return; 348 | } 349 | } 350 | } 351 | 352 | man.SaveAccount(account, passKey != null, passKey); 353 | if (IsRefreshing) 354 | { 355 | MessageBox.Show("Your login session was refreshed."); 356 | } 357 | else 358 | { 359 | MessageBox.Show("Mobile authenticator successfully linked. Please write down your revocation code: " + account.RevocationCode); 360 | } 361 | this.Close(); 362 | } 363 | 364 | private void LoginForm_Load(object sender, EventArgs e) 365 | { 366 | if (account != null && account.AccountName != null) 367 | { 368 | txtUsername.Text = account.AccountName; 369 | } 370 | } 371 | 372 | public enum LoginType 373 | { 374 | Initial, 375 | Refresh 376 | } 377 | } 378 | } 379 | -------------------------------------------------------------------------------- /Steam Desktop Authenticator/Manifest.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using SteamAuth; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace Steam_Desktop_Authenticator 12 | { 13 | public class Manifest 14 | { 15 | [JsonProperty("encrypted")] 16 | public bool Encrypted { get; set; } 17 | 18 | [JsonProperty("first_run")] 19 | public bool FirstRun { get; set; } = true; 20 | 21 | [JsonProperty("entries")] 22 | public List Entries { get; set; } 23 | 24 | [JsonProperty("periodic_checking")] 25 | public bool PeriodicChecking { get; set; } = false; 26 | 27 | [JsonProperty("periodic_checking_interval")] 28 | public int PeriodicCheckingInterval { get; set; } = 5; 29 | 30 | [JsonProperty("periodic_checking_checkall")] 31 | public bool CheckAllAccounts { get; set; } = false; 32 | 33 | [JsonProperty("auto_confirm_market_transactions")] 34 | public bool AutoConfirmMarketTransactions { get; set; } = false; 35 | 36 | [JsonProperty("auto_confirm_trades")] 37 | public bool AutoConfirmTrades { get; set; } = false; 38 | 39 | private static Manifest _manifest { get; set; } 40 | 41 | public static string GetExecutableDir() 42 | { 43 | return Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location); 44 | } 45 | 46 | public static Manifest GetManifest(bool forceLoad = false) 47 | { 48 | // Check if already staticly loaded 49 | if (_manifest != null && !forceLoad) 50 | { 51 | return _manifest; 52 | } 53 | 54 | // Find config dir and manifest file 55 | string maDir = Manifest.GetExecutableDir() + "/maFiles/"; 56 | string manifestFile = maDir + "manifest.json"; 57 | 58 | // If there's no config dir, create it 59 | if (!Directory.Exists(maDir)) 60 | { 61 | _manifest = GenerateNewManifest(false); 62 | return _manifest; 63 | } 64 | 65 | // If there's no manifest, throw exception 66 | if (!File.Exists(manifestFile)) 67 | { 68 | throw new ManifestParseException(); 69 | } 70 | 71 | try 72 | { 73 | string manifestContents = File.ReadAllText(manifestFile); 74 | _manifest = JsonConvert.DeserializeObject(manifestContents); 75 | 76 | if (_manifest.Encrypted && _manifest.Entries.Count == 0) 77 | { 78 | _manifest.Encrypted = false; 79 | _manifest.Save(); 80 | } 81 | 82 | _manifest.RecomputeExistingEntries(); 83 | 84 | return _manifest; 85 | } 86 | catch (Exception) 87 | { 88 | throw new ManifestParseException(); 89 | } 90 | } 91 | 92 | public static Manifest GenerateNewManifest(bool scanDir = false) 93 | { 94 | // No directory means no manifest file anyways. 95 | Manifest newManifest = new Manifest(); 96 | newManifest.Encrypted = false; 97 | newManifest.PeriodicCheckingInterval = 5; 98 | newManifest.PeriodicChecking = false; 99 | newManifest.AutoConfirmMarketTransactions = false; 100 | newManifest.AutoConfirmTrades = false; 101 | newManifest.Entries = new List(); 102 | newManifest.FirstRun = true; 103 | 104 | // Take a pre-manifest version and generate a manifest for it. 105 | if (scanDir) 106 | { 107 | string maDir = Manifest.GetExecutableDir() + "/maFiles/"; 108 | if (Directory.Exists(maDir)) 109 | { 110 | DirectoryInfo dir = new DirectoryInfo(maDir); 111 | var files = dir.GetFiles(); 112 | 113 | foreach (var file in files) 114 | { 115 | if (file.Extension != ".maFile") continue; 116 | 117 | string contents = File.ReadAllText(file.FullName); 118 | try 119 | { 120 | SteamGuardAccount account = JsonConvert.DeserializeObject(contents); 121 | ManifestEntry newEntry = new ManifestEntry() 122 | { 123 | Filename = file.Name, 124 | SteamID = account.Session.SteamID 125 | }; 126 | newManifest.Entries.Add(newEntry); 127 | } 128 | catch (Exception) 129 | { 130 | throw new MaFileEncryptedException(); 131 | } 132 | } 133 | 134 | if (newManifest.Entries.Count > 0) 135 | { 136 | newManifest.Save(); 137 | newManifest.PromptSetupPassKey("This version of SDA has encryption. Please enter a passkey below, or hit cancel to remain unencrypted"); 138 | } 139 | } 140 | } 141 | 142 | if (newManifest.Save()) 143 | { 144 | return newManifest; 145 | } 146 | 147 | return null; 148 | } 149 | 150 | public class IncorrectPassKeyException : Exception { } 151 | public class ManifestNotEncryptedException : Exception { } 152 | 153 | public string PromptForPassKey() 154 | { 155 | if (!this.Encrypted) 156 | { 157 | throw new ManifestNotEncryptedException(); 158 | } 159 | 160 | bool passKeyValid = false; 161 | string passKey = null; 162 | while (!passKeyValid) 163 | { 164 | InputForm passKeyForm = new InputForm("Please enter your encryption passkey.", true); 165 | passKeyForm.ShowDialog(); 166 | if (!passKeyForm.Canceled) 167 | { 168 | passKey = passKeyForm.txtBox.Text; 169 | passKeyValid = this.VerifyPasskey(passKey); 170 | if (!passKeyValid) 171 | { 172 | MessageBox.Show("That passkey is invalid."); 173 | } 174 | } 175 | else 176 | { 177 | return null; 178 | } 179 | } 180 | return passKey; 181 | } 182 | 183 | public string PromptSetupPassKey(string initialPrompt = "Enter passkey, or hit cancel to remain unencrypted.") 184 | { 185 | InputForm newPassKeyForm = new InputForm(initialPrompt); 186 | newPassKeyForm.ShowDialog(); 187 | if (newPassKeyForm.Canceled || newPassKeyForm.txtBox.Text.Length == 0) 188 | { 189 | 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."); 190 | return null; 191 | } 192 | 193 | InputForm newPassKeyForm2 = new InputForm("Confirm new passkey."); 194 | newPassKeyForm2.ShowDialog(); 195 | if (newPassKeyForm2.Canceled) 196 | { 197 | 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."); 198 | return null; 199 | } 200 | 201 | string newPassKey = newPassKeyForm.txtBox.Text; 202 | string confirmPassKey = newPassKeyForm2.txtBox.Text; 203 | 204 | if (newPassKey != confirmPassKey) 205 | { 206 | MessageBox.Show("Passkeys do not match."); 207 | return null; 208 | } 209 | 210 | if (!this.ChangeEncryptionKey(null, newPassKey)) 211 | { 212 | MessageBox.Show("Unable to set passkey."); 213 | return null; 214 | } 215 | else 216 | { 217 | MessageBox.Show("Passkey successfully set."); 218 | } 219 | 220 | return newPassKey; 221 | } 222 | 223 | public SteamAuth.SteamGuardAccount[] GetAllAccounts(string passKey = null, int limit = -1) 224 | { 225 | if (passKey == null && this.Encrypted) return new SteamGuardAccount[0]; 226 | string maDir = Manifest.GetExecutableDir() + "/maFiles/"; 227 | 228 | List accounts = new List(); 229 | foreach (var entry in this.Entries) 230 | { 231 | string fileText = File.ReadAllText(maDir + entry.Filename); 232 | if (this.Encrypted) 233 | { 234 | string decryptedText = FileEncryptor.DecryptData(passKey, entry.Salt, entry.IV, fileText); 235 | if (decryptedText == null) return new SteamGuardAccount[0]; 236 | fileText = decryptedText; 237 | } 238 | 239 | var account = JsonConvert.DeserializeObject(fileText); 240 | if (account == null) continue; 241 | accounts.Add(account); 242 | 243 | if (limit != -1 && limit >= accounts.Count) 244 | break; 245 | } 246 | 247 | return accounts.ToArray(); 248 | } 249 | 250 | public bool ChangeEncryptionKey(string oldKey, string newKey) 251 | { 252 | if (this.Encrypted) 253 | { 254 | if (!this.VerifyPasskey(oldKey)) 255 | { 256 | return false; 257 | } 258 | } 259 | bool toEncrypt = newKey != null; 260 | 261 | string maDir = Manifest.GetExecutableDir() + "/maFiles/"; 262 | for (int i = 0; i < this.Entries.Count; i++) 263 | { 264 | ManifestEntry entry = this.Entries[i]; 265 | string filename = maDir + entry.Filename; 266 | if (!File.Exists(filename)) continue; 267 | 268 | string fileContents = File.ReadAllText(filename); 269 | if (this.Encrypted) 270 | { 271 | fileContents = FileEncryptor.DecryptData(oldKey, entry.Salt, entry.IV, fileContents); 272 | } 273 | 274 | string newSalt = null; 275 | string newIV = null; 276 | string toWriteFileContents = fileContents; 277 | 278 | if (toEncrypt) 279 | { 280 | newSalt = FileEncryptor.GetRandomSalt(); 281 | newIV = FileEncryptor.GetInitializationVector(); 282 | toWriteFileContents = FileEncryptor.EncryptData(newKey, newSalt, newIV, fileContents); 283 | } 284 | 285 | File.WriteAllText(filename, toWriteFileContents); 286 | entry.IV = newIV; 287 | entry.Salt = newSalt; 288 | } 289 | 290 | this.Encrypted = toEncrypt; 291 | 292 | this.Save(); 293 | return true; 294 | } 295 | 296 | public bool VerifyPasskey(string passkey) 297 | { 298 | if (!this.Encrypted || this.Entries.Count == 0) return true; 299 | 300 | var accounts = this.GetAllAccounts(passkey, 1); 301 | return accounts != null && accounts.Length == 1; 302 | } 303 | 304 | public bool RemoveAccount(SteamGuardAccount account, bool deleteMaFile = true) 305 | { 306 | ManifestEntry entry = (from e in this.Entries where e.SteamID == account.Session.SteamID select e).FirstOrDefault(); 307 | if (entry == null) return true; // If something never existed, did you do what they asked? 308 | 309 | string maDir = Manifest.GetExecutableDir() + "/maFiles/"; 310 | string filename = maDir + entry.Filename; 311 | this.Entries.Remove(entry); 312 | 313 | if (this.Entries.Count == 0) 314 | { 315 | this.Encrypted = false; 316 | } 317 | 318 | if (this.Save() && deleteMaFile) 319 | { 320 | try 321 | { 322 | File.Delete(filename); 323 | return true; 324 | } 325 | catch (Exception) 326 | { 327 | return false; 328 | } 329 | } 330 | 331 | return false; 332 | } 333 | 334 | public bool SaveAccount(SteamGuardAccount account, bool encrypt, string passKey = null) 335 | { 336 | if (encrypt && String.IsNullOrEmpty(passKey)) return false; 337 | if (!encrypt && this.Encrypted) return false; 338 | 339 | string salt = null; 340 | string iV = null; 341 | string jsonAccount = JsonConvert.SerializeObject(account); 342 | 343 | if (encrypt) 344 | { 345 | salt = FileEncryptor.GetRandomSalt(); 346 | iV = FileEncryptor.GetInitializationVector(); 347 | string encrypted = FileEncryptor.EncryptData(passKey, salt, iV, jsonAccount); 348 | if (encrypted == null) return false; 349 | jsonAccount = encrypted; 350 | } 351 | 352 | string maDir = Manifest.GetExecutableDir() + "/maFiles/"; 353 | string filename = account.Session.SteamID.ToString() + ".maFile"; 354 | 355 | ManifestEntry newEntry = new ManifestEntry() 356 | { 357 | SteamID = account.Session.SteamID, 358 | IV = iV, 359 | Salt = salt, 360 | Filename = filename 361 | }; 362 | 363 | bool foundExistingEntry = false; 364 | for (int i = 0; i < this.Entries.Count; i++) 365 | { 366 | if (this.Entries[i].SteamID == account.Session.SteamID) 367 | { 368 | this.Entries[i] = newEntry; 369 | foundExistingEntry = true; 370 | break; 371 | } 372 | } 373 | 374 | if (!foundExistingEntry) 375 | { 376 | this.Entries.Add(newEntry); 377 | } 378 | 379 | bool wasEncrypted = this.Encrypted; 380 | this.Encrypted = encrypt || this.Encrypted; 381 | 382 | if (!this.Save()) 383 | { 384 | this.Encrypted = wasEncrypted; 385 | return false; 386 | } 387 | 388 | try 389 | { 390 | File.WriteAllText(maDir + filename, jsonAccount); 391 | return true; 392 | } 393 | catch (Exception) 394 | { 395 | return false; 396 | } 397 | } 398 | 399 | public bool Save() 400 | { 401 | string maDir = Manifest.GetExecutableDir() + "/maFiles/"; 402 | string filename = maDir + "manifest.json"; 403 | if (!Directory.Exists(maDir)) 404 | { 405 | try 406 | { 407 | Directory.CreateDirectory(maDir); 408 | } 409 | catch (Exception) 410 | { 411 | return false; 412 | } 413 | } 414 | 415 | try 416 | { 417 | string contents = JsonConvert.SerializeObject(this); 418 | File.WriteAllText(filename, contents); 419 | return true; 420 | } 421 | catch (Exception) 422 | { 423 | return false; 424 | } 425 | } 426 | 427 | private void RecomputeExistingEntries() 428 | { 429 | List newEntries = new List(); 430 | string maDir = Manifest.GetExecutableDir() + "/maFiles/"; 431 | 432 | foreach (var entry in this.Entries) 433 | { 434 | string filename = maDir + entry.Filename; 435 | if (File.Exists(filename)) 436 | { 437 | newEntries.Add(entry); 438 | } 439 | } 440 | 441 | this.Entries = newEntries; 442 | 443 | if (this.Entries.Count == 0) 444 | { 445 | this.Encrypted = false; 446 | } 447 | } 448 | 449 | public void MoveEntry(int from, int to) 450 | { 451 | if (from < 0 || to < 0 || from > Entries.Count || to > Entries.Count - 1) return; 452 | ManifestEntry sel = Entries[from]; 453 | Entries.RemoveAt(from); 454 | Entries.Insert(to, sel); 455 | Save(); 456 | } 457 | 458 | public class ManifestEntry 459 | { 460 | [JsonProperty("encryption_iv")] 461 | public string IV { get; set; } 462 | 463 | [JsonProperty("encryption_salt")] 464 | public string Salt { get; set; } 465 | 466 | [JsonProperty("filename")] 467 | public string Filename { get; set; } 468 | 469 | [JsonProperty("steamid")] 470 | public ulong SteamID { get; set; } 471 | } 472 | } 473 | } 474 | --------------------------------------------------------------------------------