mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2025-12-20 08:18:37 +00:00
Add support for encrypted passwords, closes #267
This commit is contained in:
@@ -1,4 +1,9 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">TOGETHER</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHING_EMPTY_BRACES/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AES/@EntryIndexedValue">AES</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=API/@EntryIndexedValue">API</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ASF/@EntryIndexedValue">ASF</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=FA/@EntryIndexedValue">FA</s:String>
|
||||
@@ -15,4 +20,7 @@
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=WTF/@EntryIndexedValue">WTF</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XML/@EntryIndexedValue">XML</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="_" Suffix="" Style="AaBb" /><ExtraRule Prefix="_" Suffix="" Style="aaBb" /></Policy></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="_" Suffix="" Style="aaBb" /></Policy></s:String></wpf:ResourceDictionary>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="_" Suffix="" Style="aaBb" /></Policy></s:String>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@@ -101,6 +101,7 @@
|
||||
<Compile Include="BotConfig.cs" />
|
||||
<Compile Include="ConcurrentEnumerator.cs" />
|
||||
<Compile Include="ConcurrentHashSet.cs" />
|
||||
<Compile Include="CryptoHelper.cs" />
|
||||
<Compile Include="GlobalDatabase.cs" />
|
||||
<Compile Include="BotDatabase.cs" />
|
||||
<Compile Include="CardsFarmer.cs" />
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace ArchiSteamFarm {
|
||||
string sessionID = Convert.ToBase64String(Encoding.UTF8.GetBytes(SteamID.ToString()));
|
||||
|
||||
// Generate an AES session key
|
||||
byte[] sessionKey = CryptoHelper.GenerateRandomBlock(32);
|
||||
byte[] sessionKey = SteamKit2.CryptoHelper.GenerateRandomBlock(32);
|
||||
|
||||
// RSA encrypt it with the public key for the universe we're on
|
||||
byte[] cryptedSessionKey;
|
||||
@@ -140,7 +140,7 @@ namespace ArchiSteamFarm {
|
||||
Array.Copy(Encoding.ASCII.GetBytes(webAPIUserNonce), loginKey, webAPIUserNonce.Length);
|
||||
|
||||
// AES encrypt the loginkey with our session key
|
||||
byte[] cryptedLoginKey = CryptoHelper.SymmetricEncrypt(loginKey, sessionKey);
|
||||
byte[] cryptedLoginKey = SteamKit2.CryptoHelper.SymmetricEncrypt(loginKey, sessionKey);
|
||||
|
||||
// Do the magic
|
||||
Logging.LogGenericInfo("Logging in to ISteamUserAuth...", Bot.BotName);
|
||||
|
||||
@@ -385,6 +385,8 @@ namespace ArchiSteamFarm {
|
||||
return await ResponseLoot(steamID).ConfigureAwait(false);
|
||||
case "!LOOTALL":
|
||||
return await ResponseLootAll(steamID).ConfigureAwait(false);
|
||||
case "!PASSWORD":
|
||||
return ResponsePassword(steamID);
|
||||
case "!PAUSE":
|
||||
return await ResponsePause(steamID, true).ConfigureAwait(false);
|
||||
case "!REJOINCHAT":
|
||||
@@ -432,6 +434,8 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
return await ResponseOwns(steamID, BotName, args[1]).ConfigureAwait(false);
|
||||
case "!PASSWORD":
|
||||
return ResponsePassword(steamID, args[1]);
|
||||
case "!PAUSE":
|
||||
return await ResponsePause(steamID, args[1], true).ConfigureAwait(false);
|
||||
case "!PLAY":
|
||||
@@ -530,6 +534,44 @@ namespace ArchiSteamFarm {
|
||||
Logging.LogGenericInfo("Successfully finished importing mobile authenticator!", BotName);
|
||||
}
|
||||
|
||||
private string ResponsePassword(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
Logging.LogNullError(nameof(steamID), BotName);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamPassword)) {
|
||||
return "Can't encrypt null password!";
|
||||
}
|
||||
|
||||
return Environment.NewLine +
|
||||
"Password length: " + BotConfig.SteamPassword.Length + Environment.NewLine +
|
||||
CryptoHelper.ECryptoMethod.Base64 + " encrypted: " + CryptoHelper.Encrypt(CryptoHelper.ECryptoMethod.Base64, BotConfig.SteamPassword) + Environment.NewLine +
|
||||
CryptoHelper.ECryptoMethod.AES + " encrypted: " + CryptoHelper.Encrypt(CryptoHelper.ECryptoMethod.AES, BotConfig.SteamPassword);
|
||||
}
|
||||
|
||||
private static string ResponsePassword(ulong steamID, string botName) {
|
||||
if ((steamID == 0) || string.IsNullOrEmpty(botName)) {
|
||||
Logging.LogNullError(nameof(steamID) + " || " + nameof(botName));
|
||||
return null;
|
||||
}
|
||||
|
||||
Bot bot;
|
||||
if (Bots.TryGetValue(botName, out bot)) {
|
||||
return bot.ResponsePassword(steamID);
|
||||
}
|
||||
|
||||
if (IsOwner(steamID)) {
|
||||
return "Couldn't find any bot named " + botName + "!";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<string> ResponsePause(ulong steamID, bool pause) {
|
||||
if (steamID == 0) {
|
||||
Logging.LogNullError(nameof(steamID), BotName);
|
||||
@@ -1466,7 +1508,7 @@ namespace ArchiSteamFarm {
|
||||
if (File.Exists(SentryFile)) {
|
||||
try {
|
||||
byte[] sentryFileContent = File.ReadAllBytes(SentryFile);
|
||||
sentryHash = CryptoHelper.SHAHash(sentryFileContent);
|
||||
sentryHash = SteamKit2.CryptoHelper.SHAHash(sentryFileContent);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, BotName);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,10 @@ namespace ArchiSteamFarm {
|
||||
[JsonProperty]
|
||||
internal string SteamPassword { get; set; }
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
[SuppressMessage("ReSharper", "ConvertToConstant.Local")]
|
||||
private readonly CryptoHelper.ECryptoMethod PasswordFormat = CryptoHelper.ECryptoMethod.PlainText;
|
||||
|
||||
[JsonProperty]
|
||||
internal string SteamParentalPIN { get; set; } = "0";
|
||||
|
||||
@@ -125,6 +129,12 @@ namespace ArchiSteamFarm {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Support encrypted passwords
|
||||
if (!string.IsNullOrEmpty(botConfig.SteamPassword) && (botConfig.PasswordFormat != CryptoHelper.ECryptoMethod.PlainText)) {
|
||||
// In worst case password will result in null, which will have to be corrected by user during runtime
|
||||
botConfig.SteamPassword = CryptoHelper.Decrypt(botConfig.PasswordFormat, botConfig.SteamPassword);
|
||||
}
|
||||
|
||||
// User might not know what he's doing
|
||||
// Ensure that he can't screw core ASF variables
|
||||
if (botConfig.GamesPlayedWhileIdle.Count <= CardsFarmer.MaxGamesPlayedConcurrently) {
|
||||
|
||||
147
ArchiSteamFarm/CryptoHelper.cs
Normal file
147
ArchiSteamFarm/CryptoHelper.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
_ _ _ ____ _ _____
|
||||
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
|
||||
Copyright 2015-2016 Łukasz "JustArchi" Domeradzki
|
||||
Contact: JustArchi@JustArchi.net
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal static class CryptoHelper {
|
||||
internal enum ECryptoMethod : byte {
|
||||
PlainText,
|
||||
Base64,
|
||||
AES
|
||||
}
|
||||
|
||||
private static readonly byte[] EncryptionKey = Encoding.UTF8.GetBytes("ArchiSteamFarm");
|
||||
|
||||
internal static string Encrypt(ECryptoMethod cryptoMethod, string decrypted) {
|
||||
if (string.IsNullOrEmpty(decrypted)) {
|
||||
Logging.LogNullError(nameof(decrypted));
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (cryptoMethod) {
|
||||
case ECryptoMethod.PlainText:
|
||||
return decrypted;
|
||||
case ECryptoMethod.Base64:
|
||||
return EncryptBase64(decrypted);
|
||||
case ECryptoMethod.AES:
|
||||
return EncryptAES(decrypted);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static string Decrypt(ECryptoMethod cryptoMethod, string encrypted) {
|
||||
if (string.IsNullOrEmpty(encrypted)) {
|
||||
Logging.LogNullError(nameof(encrypted));
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (cryptoMethod) {
|
||||
case ECryptoMethod.PlainText:
|
||||
return encrypted;
|
||||
case ECryptoMethod.Base64:
|
||||
return DecryptBase64(encrypted);
|
||||
case ECryptoMethod.AES:
|
||||
return DecryptAES(encrypted);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static string EncryptBase64(string decrypted) {
|
||||
if (string.IsNullOrEmpty(decrypted)) {
|
||||
Logging.LogNullError(nameof(decrypted));
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] data = Encoding.UTF8.GetBytes(decrypted);
|
||||
return Convert.ToBase64String(data);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static string DecryptBase64(string encrypted) {
|
||||
if (string.IsNullOrEmpty(encrypted)) {
|
||||
Logging.LogNullError(nameof(encrypted));
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] data = Convert.FromBase64String(encrypted);
|
||||
return Encoding.UTF8.GetString(data);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static string EncryptAES(string decrypted) {
|
||||
if (string.IsNullOrEmpty(decrypted)) {
|
||||
Logging.LogNullError(nameof(decrypted));
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] key;
|
||||
using (SHA256Managed sha256 = new SHA256Managed()) {
|
||||
key = sha256.ComputeHash(EncryptionKey);
|
||||
}
|
||||
|
||||
byte[] data = Encoding.UTF8.GetBytes(decrypted);
|
||||
byte[] encrypted = SteamKit2.CryptoHelper.SymmetricEncrypt(data, key);
|
||||
return Convert.ToBase64String(encrypted);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static string DecryptAES(string encrypted) {
|
||||
if (string.IsNullOrEmpty(encrypted)) {
|
||||
Logging.LogNullError(nameof(encrypted));
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] key;
|
||||
using (SHA256Managed sha256 = new SHA256Managed()) {
|
||||
key = sha256.ComputeHash(EncryptionKey);
|
||||
}
|
||||
|
||||
byte[] data = Convert.FromBase64String(encrypted);
|
||||
byte[] decrypted = SteamKit2.CryptoHelper.SymmetricDecrypt(data, key);
|
||||
return Encoding.UTF8.GetString(decrypted);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
"StartOnLaunch": true,
|
||||
"SteamLogin": null,
|
||||
"SteamPassword": null,
|
||||
"PasswordFormat": 1,
|
||||
"SteamParentalPIN": "0",
|
||||
"SteamApiKey": null,
|
||||
"SteamMasterID": 0,
|
||||
|
||||
@@ -35,6 +35,12 @@ namespace ConfigGenerator {
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
internal sealed class BotConfig : ASFConfig {
|
||||
internal enum ECryptoMethod : byte {
|
||||
PlainText,
|
||||
Base64,
|
||||
AES
|
||||
}
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public bool Enabled { get; set; } = false;
|
||||
|
||||
@@ -48,6 +54,9 @@ namespace ConfigGenerator {
|
||||
[PasswordPropertyText(true)]
|
||||
public string SteamPassword { get; set; } = null;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public ECryptoMethod PasswordFormat { get; set; } = ECryptoMethod.PlainText;
|
||||
|
||||
[JsonProperty]
|
||||
public string SteamParentalPIN { get; set; } = "0";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user