mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2026-01-01 14:10:53 +00:00
Slightly improve password generation
This commit is contained in:
@@ -31,43 +31,24 @@ using SteamKit2;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
public static class ArchiCryptoHelper {
|
||||
[ItemNotNull]
|
||||
private const ushort SteamParentalPbkdf2Iterations = 10000;
|
||||
private const byte SteamParentalSCryptBlocksCount = 8;
|
||||
private const ushort SteamParentalSCryptIterations = 8192;
|
||||
|
||||
[NotNull]
|
||||
private static IEnumerable<byte> SteamParentalCharacters => Enumerable.Range('0', 10).Select(character => (byte) character);
|
||||
|
||||
[NotNull]
|
||||
private static IEnumerable<byte[]> SteamParentalCodes {
|
||||
get {
|
||||
for (char a = '0'; a <= '9'; a++) {
|
||||
for (char b = '0'; b <= '9'; b++) {
|
||||
for (char c = '0'; c <= '9'; c++) {
|
||||
for (char d = '0'; d <= '9'; d++) {
|
||||
yield return new[] { (byte) a, (byte) b, (byte) c, (byte) d };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HashSet<byte> steamParentalCharacters = SteamParentalCharacters.ToHashSet();
|
||||
|
||||
return from a in steamParentalCharacters from b in steamParentalCharacters from c in steamParentalCharacters from d in steamParentalCharacters select new[] { a, b, c, d };
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] EncryptionKey = Encoding.UTF8.GetBytes(nameof(ArchiSteamFarm));
|
||||
|
||||
internal static string BruteforceSteamParentalCode(byte[] passwordHash, byte[] salt, bool scrypt = true) {
|
||||
if ((passwordHash == null) || (salt == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(passwordHash) + " || " + nameof(salt));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] password = scrypt
|
||||
? SteamParentalCodes.AsParallel().FirstOrDefault(passwordToTry => passwordHash.SequenceEqual(SCrypt.ComputeDerivedKey(passwordToTry, salt, 8192, 8, 1, null, passwordHash.Length)))
|
||||
: SteamParentalCodes.AsParallel().FirstOrDefault(
|
||||
passwordToTry => {
|
||||
using (HMACSHA1 hmacAlgorithm = new HMACSHA1(passwordToTry)) {
|
||||
return passwordHash.SequenceEqual(Pbkdf2.ComputeDerivedKey(hmacAlgorithm, salt, 10000, passwordHash.Length));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return password != null ? Encoding.UTF8.GetString(password) : null;
|
||||
}
|
||||
|
||||
internal static string Decrypt(ECryptoMethod cryptoMethod, string encrypted) {
|
||||
if (!Enum.IsDefined(typeof(ECryptoMethod), cryptoMethod) || string.IsNullOrEmpty(encrypted)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(cryptoMethod) + " || " + nameof(encrypted));
|
||||
@@ -110,6 +91,39 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
internal static byte[] GenerateSteamParentalHash(byte[] password, byte[] salt, byte hashLength, ESteamParentalAlgorithm steamParentalAlgorithm) {
|
||||
if ((password == null) || (salt == null) || (hashLength == 0) || !Enum.IsDefined(typeof(ESteamParentalAlgorithm), steamParentalAlgorithm)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(password) + " || " + nameof(salt) + " || " + nameof(hashLength) + " || " + nameof(steamParentalAlgorithm));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (steamParentalAlgorithm) {
|
||||
case ESteamParentalAlgorithm.Pbkdf2:
|
||||
using (HMACSHA1 hmacAlgorithm = new HMACSHA1(password)) {
|
||||
return Pbkdf2.ComputeDerivedKey(hmacAlgorithm, salt, SteamParentalPbkdf2Iterations, hashLength);
|
||||
}
|
||||
case ESteamParentalAlgorithm.SCrypt:
|
||||
return SCrypt.ComputeDerivedKey(password, salt, SteamParentalSCryptIterations, SteamParentalSCryptBlocksCount, 1, null, hashLength);
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(steamParentalAlgorithm), steamParentalAlgorithm));
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static string RecoverSteamParentalCode(byte[] passwordHash, byte[] salt, ESteamParentalAlgorithm steamParentalAlgorithm) {
|
||||
if ((passwordHash == null) || (salt == null) || !Enum.IsDefined(typeof(ESteamParentalAlgorithm), steamParentalAlgorithm)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(passwordHash) + " || " + nameof(salt) + " || " + nameof(steamParentalAlgorithm));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] password = SteamParentalCodes.AsParallel().FirstOrDefault(passwordToTry => GenerateSteamParentalHash(passwordToTry, salt, (byte) passwordHash.Length, steamParentalAlgorithm)?.SequenceEqual(passwordHash) == true);
|
||||
|
||||
return password != null ? Encoding.UTF8.GetString(password) : null;
|
||||
}
|
||||
|
||||
internal static void SetEncryptionKey(string key) {
|
||||
if (string.IsNullOrEmpty(key)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(key));
|
||||
@@ -227,5 +241,10 @@ namespace ArchiSteamFarm {
|
||||
AES,
|
||||
ProtectedDataForCurrentUser
|
||||
}
|
||||
|
||||
internal enum ESteamParentalAlgorithm : byte {
|
||||
SCrypt,
|
||||
Pbkdf2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,12 +25,10 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using ArchiSteamFarm.CMsgs;
|
||||
using ArchiSteamFarm.Localization;
|
||||
using ArchiSteamFarm.NLog;
|
||||
using CryptSharp.Utility;
|
||||
using JetBrains.Annotations;
|
||||
using SteamKit2;
|
||||
using SteamKit2.Internal;
|
||||
@@ -666,15 +664,15 @@ namespace ArchiSteamFarm {
|
||||
return (false, null);
|
||||
}
|
||||
|
||||
bool scrypt;
|
||||
ArchiCryptoHelper.ESteamParentalAlgorithm steamParentalAlgorithm;
|
||||
|
||||
switch (body.settings.passwordhashtype) {
|
||||
case 4:
|
||||
scrypt = false;
|
||||
steamParentalAlgorithm = ArchiCryptoHelper.ESteamParentalAlgorithm.Pbkdf2;
|
||||
|
||||
break;
|
||||
case 6:
|
||||
scrypt = true;
|
||||
steamParentalAlgorithm = ArchiCryptoHelper.ESteamParentalAlgorithm.SCrypt;
|
||||
|
||||
break;
|
||||
default:
|
||||
@@ -696,15 +694,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
if (i >= steamParentalCode.Length) {
|
||||
byte[] passwordHash;
|
||||
|
||||
if (scrypt) {
|
||||
passwordHash = SCrypt.ComputeDerivedKey(password, body.settings.salt, 8192, 8, 1, null, body.settings.passwordhash.Length);
|
||||
} else {
|
||||
using (HMACSHA1 hmacAlgorithm = new HMACSHA1(password)) {
|
||||
passwordHash = Pbkdf2.ComputeDerivedKey(hmacAlgorithm, body.settings.salt, 10000, body.settings.passwordhash.Length);
|
||||
}
|
||||
}
|
||||
byte[] passwordHash = ArchiCryptoHelper.GenerateSteamParentalHash(password, body.settings.salt, (byte) body.settings.passwordhash.Length, steamParentalAlgorithm);
|
||||
|
||||
if (passwordHash.SequenceEqual(body.settings.passwordhash)) {
|
||||
return (true, steamParentalCode);
|
||||
@@ -712,9 +702,9 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
ArchiLogger.LogGenericInfo(Strings.PleaseWait);
|
||||
ArchiLogger.LogGenericInfo(Strings.BotGeneratingSteamParentalCode);
|
||||
|
||||
steamParentalCode = ArchiCryptoHelper.BruteforceSteamParentalCode(body.settings.passwordhash, body.settings.salt, scrypt);
|
||||
steamParentalCode = ArchiCryptoHelper.RecoverSteamParentalCode(body.settings.passwordhash, body.settings.salt, steamParentalAlgorithm);
|
||||
|
||||
ArchiLogger.LogGenericInfo(Strings.Done);
|
||||
|
||||
|
||||
11
ArchiSteamFarm/Localization/Strings.Designer.cs
generated
11
ArchiSteamFarm/Localization/Strings.Designer.cs
generated
@@ -19,7 +19,7 @@ namespace ArchiSteamFarm.Localization {
|
||||
// przez narzędzie, takie jak ResGen lub Visual Studio.
|
||||
// Aby dodać lub usunąć składową, edytuj plik ResX, a następnie ponownie uruchom narzędzie ResGen
|
||||
// z opcją /str lub ponownie utwórz projekt VS.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Strings {
|
||||
@@ -330,6 +330,15 @@ namespace ArchiSteamFarm.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wyszukuje zlokalizowany ciąg podobny do ciągu Generating Steam parental code, this can take a while, consider putting it in the config instead....
|
||||
/// </summary>
|
||||
public static string BotGeneratingSteamParentalCode {
|
||||
get {
|
||||
return ResourceManager.GetString("BotGeneratingSteamParentalCode", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wyszukuje zlokalizowany ciąg podobny do ciągu Successfully handled {0} confirmations!.
|
||||
/// </summary>
|
||||
|
||||
@@ -731,4 +731,7 @@ StackTrace:
|
||||
<data name="UpdateCleanup" xml:space="preserve">
|
||||
<value>Cleaning up old files after update...</value>
|
||||
</data>
|
||||
<data name="BotGeneratingSteamParentalCode" xml:space="preserve">
|
||||
<value>Generating Steam parental code, this can take a while, consider putting it in the config instead...</value>
|
||||
</data>
|
||||
</root>
|
||||
Reference in New Issue
Block a user