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">
|
<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/=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/=ASF/@EntryIndexedValue">ASF</s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=FA/@EntryIndexedValue">FA</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/=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/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/=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="BotConfig.cs" />
|
||||||
<Compile Include="ConcurrentEnumerator.cs" />
|
<Compile Include="ConcurrentEnumerator.cs" />
|
||||||
<Compile Include="ConcurrentHashSet.cs" />
|
<Compile Include="ConcurrentHashSet.cs" />
|
||||||
|
<Compile Include="CryptoHelper.cs" />
|
||||||
<Compile Include="GlobalDatabase.cs" />
|
<Compile Include="GlobalDatabase.cs" />
|
||||||
<Compile Include="BotDatabase.cs" />
|
<Compile Include="BotDatabase.cs" />
|
||||||
<Compile Include="CardsFarmer.cs" />
|
<Compile Include="CardsFarmer.cs" />
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ namespace ArchiSteamFarm {
|
|||||||
string sessionID = Convert.ToBase64String(Encoding.UTF8.GetBytes(SteamID.ToString()));
|
string sessionID = Convert.ToBase64String(Encoding.UTF8.GetBytes(SteamID.ToString()));
|
||||||
|
|
||||||
// Generate an AES session key
|
// 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
|
// RSA encrypt it with the public key for the universe we're on
|
||||||
byte[] cryptedSessionKey;
|
byte[] cryptedSessionKey;
|
||||||
@@ -140,7 +140,7 @@ namespace ArchiSteamFarm {
|
|||||||
Array.Copy(Encoding.ASCII.GetBytes(webAPIUserNonce), loginKey, webAPIUserNonce.Length);
|
Array.Copy(Encoding.ASCII.GetBytes(webAPIUserNonce), loginKey, webAPIUserNonce.Length);
|
||||||
|
|
||||||
// AES encrypt the loginkey with our session key
|
// AES encrypt the loginkey with our session key
|
||||||
byte[] cryptedLoginKey = CryptoHelper.SymmetricEncrypt(loginKey, sessionKey);
|
byte[] cryptedLoginKey = SteamKit2.CryptoHelper.SymmetricEncrypt(loginKey, sessionKey);
|
||||||
|
|
||||||
// Do the magic
|
// Do the magic
|
||||||
Logging.LogGenericInfo("Logging in to ISteamUserAuth...", Bot.BotName);
|
Logging.LogGenericInfo("Logging in to ISteamUserAuth...", Bot.BotName);
|
||||||
|
|||||||
@@ -385,6 +385,8 @@ namespace ArchiSteamFarm {
|
|||||||
return await ResponseLoot(steamID).ConfigureAwait(false);
|
return await ResponseLoot(steamID).ConfigureAwait(false);
|
||||||
case "!LOOTALL":
|
case "!LOOTALL":
|
||||||
return await ResponseLootAll(steamID).ConfigureAwait(false);
|
return await ResponseLootAll(steamID).ConfigureAwait(false);
|
||||||
|
case "!PASSWORD":
|
||||||
|
return ResponsePassword(steamID);
|
||||||
case "!PAUSE":
|
case "!PAUSE":
|
||||||
return await ResponsePause(steamID, true).ConfigureAwait(false);
|
return await ResponsePause(steamID, true).ConfigureAwait(false);
|
||||||
case "!REJOINCHAT":
|
case "!REJOINCHAT":
|
||||||
@@ -432,6 +434,8 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return await ResponseOwns(steamID, BotName, args[1]).ConfigureAwait(false);
|
return await ResponseOwns(steamID, BotName, args[1]).ConfigureAwait(false);
|
||||||
|
case "!PASSWORD":
|
||||||
|
return ResponsePassword(steamID, args[1]);
|
||||||
case "!PAUSE":
|
case "!PAUSE":
|
||||||
return await ResponsePause(steamID, args[1], true).ConfigureAwait(false);
|
return await ResponsePause(steamID, args[1], true).ConfigureAwait(false);
|
||||||
case "!PLAY":
|
case "!PLAY":
|
||||||
@@ -530,6 +534,44 @@ namespace ArchiSteamFarm {
|
|||||||
Logging.LogGenericInfo("Successfully finished importing mobile authenticator!", BotName);
|
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) {
|
private async Task<string> ResponsePause(ulong steamID, bool pause) {
|
||||||
if (steamID == 0) {
|
if (steamID == 0) {
|
||||||
Logging.LogNullError(nameof(steamID), BotName);
|
Logging.LogNullError(nameof(steamID), BotName);
|
||||||
@@ -1466,7 +1508,7 @@ namespace ArchiSteamFarm {
|
|||||||
if (File.Exists(SentryFile)) {
|
if (File.Exists(SentryFile)) {
|
||||||
try {
|
try {
|
||||||
byte[] sentryFileContent = File.ReadAllBytes(SentryFile);
|
byte[] sentryFileContent = File.ReadAllBytes(SentryFile);
|
||||||
sentryHash = CryptoHelper.SHAHash(sentryFileContent);
|
sentryHash = SteamKit2.CryptoHelper.SHAHash(sentryFileContent);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logging.LogGenericException(e, BotName);
|
Logging.LogGenericException(e, BotName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ namespace ArchiSteamFarm {
|
|||||||
[JsonProperty]
|
[JsonProperty]
|
||||||
internal string SteamPassword { get; set; }
|
internal string SteamPassword { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
|
[SuppressMessage("ReSharper", "ConvertToConstant.Local")]
|
||||||
|
private readonly CryptoHelper.ECryptoMethod PasswordFormat = CryptoHelper.ECryptoMethod.PlainText;
|
||||||
|
|
||||||
[JsonProperty]
|
[JsonProperty]
|
||||||
internal string SteamParentalPIN { get; set; } = "0";
|
internal string SteamParentalPIN { get; set; } = "0";
|
||||||
|
|
||||||
@@ -125,6 +129,12 @@ namespace ArchiSteamFarm {
|
|||||||
return null;
|
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
|
// User might not know what he's doing
|
||||||
// Ensure that he can't screw core ASF variables
|
// Ensure that he can't screw core ASF variables
|
||||||
if (botConfig.GamesPlayedWhileIdle.Count <= CardsFarmer.MaxGamesPlayedConcurrently) {
|
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,
|
"StartOnLaunch": true,
|
||||||
"SteamLogin": null,
|
"SteamLogin": null,
|
||||||
"SteamPassword": null,
|
"SteamPassword": null,
|
||||||
|
"PasswordFormat": 1,
|
||||||
"SteamParentalPIN": "0",
|
"SteamParentalPIN": "0",
|
||||||
"SteamApiKey": null,
|
"SteamApiKey": null,
|
||||||
"SteamMasterID": 0,
|
"SteamMasterID": 0,
|
||||||
|
|||||||
@@ -35,6 +35,12 @@ namespace ConfigGenerator {
|
|||||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||||
internal sealed class BotConfig : ASFConfig {
|
internal sealed class BotConfig : ASFConfig {
|
||||||
|
internal enum ECryptoMethod : byte {
|
||||||
|
PlainText,
|
||||||
|
Base64,
|
||||||
|
AES
|
||||||
|
}
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
public bool Enabled { get; set; } = false;
|
public bool Enabled { get; set; } = false;
|
||||||
|
|
||||||
@@ -48,6 +54,9 @@ namespace ConfigGenerator {
|
|||||||
[PasswordPropertyText(true)]
|
[PasswordPropertyText(true)]
|
||||||
public string SteamPassword { get; set; } = null;
|
public string SteamPassword { get; set; } = null;
|
||||||
|
|
||||||
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
|
public ECryptoMethod PasswordFormat { get; set; } = ECryptoMethod.PlainText;
|
||||||
|
|
||||||
[JsonProperty]
|
[JsonProperty]
|
||||||
public string SteamParentalPIN { get; set; } = "0";
|
public string SteamParentalPIN { get; set; } = "0";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user