(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 |
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 |
--------------------------------------------------------------------------------