From 7509375b434da11b5808779a5cc1a93a4a750572 Mon Sep 17 00:00:00 2001 From: barelyprofessional <150058423+barelyprofessional@users.noreply.github.com> Date: Sun, 1 Sep 2024 20:24:20 +0800 Subject: [PATCH] Added due credit to KiwiFlare.cs for the original Go implementation I adapted this from. Also added extra logging, refactored the challenge worker, and cleaned up the code a little. --- KfChatDotNetBot/Services/KiwiFlare.cs | 40 +++++++++++++-------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/KfChatDotNetBot/Services/KiwiFlare.cs b/KfChatDotNetBot/Services/KiwiFlare.cs index 5feba92..b134489 100644 --- a/KfChatDotNetBot/Services/KiwiFlare.cs +++ b/KfChatDotNetBot/Services/KiwiFlare.cs @@ -9,20 +9,20 @@ using NLog; namespace KfChatDotNetBot.Services; +// Shoutout y a t s for making the original Go implementation I adapted for this +// https://github.com/y-a-t-s/firebird public class KiwiFlare(string kfDomain, string? proxy = null, CancellationToken? cancellationToken = null) { private readonly Logger _logger = LogManager.GetCurrentClassLogger(); - private string? _proxy = proxy; - private CancellationToken _ctx = cancellationToken ?? CancellationToken.None; - private string _kfDomain = kfDomain; - private Random _random = new Random(); + private readonly CancellationToken _ctx = cancellationToken ?? CancellationToken.None; + private readonly Random _random = new(); private HttpClientHandler GetHttpClientHandler() { var handler = new HttpClientHandler { AutomaticDecompression = DecompressionMethods.All }; - if (_proxy != null) + if (proxy != null) { - handler.Proxy = new WebProxy(_proxy); + handler.Proxy = new WebProxy(proxy); handler.UseProxy = true; } @@ -32,7 +32,7 @@ public class KiwiFlare(string kfDomain, string? proxy = null, CancellationToken? public async Task GetChallenge() { using var client = new HttpClient(GetHttpClientHandler()); - var response = await client.GetAsync($"https://{_kfDomain}/", _ctx); + var response = await client.GetAsync($"https://{kfDomain}/", _ctx); var document = new HtmlDocument(); document.Load(await response.Content.ReadAsStreamAsync(_ctx)); var challengeData = document.DocumentNode.SelectSingleNode("//html[@id=\"sssg\"]"); @@ -77,25 +77,24 @@ public class KiwiFlare(string kfDomain, string? proxy = null, CancellationToken? private async Task ChallengeWorker(KiwiFlareChallengeModel challenge) { - var found = false; var nonce = _random.NextInt64(); - while (!found) + while (true) { - // Incrementing nonce first as then I can just pass TestHash straight into found and reuse the value nonce++; var input = Encoding.UTF8.GetBytes($"{challenge.Salt}{nonce}"); - found = TestHash(SHA256.HashData(input), challenge.Difficulty); + if (!TestHash(SHA256.HashData(input), challenge.Difficulty)) continue; + _logger.Debug($"Hash passed the test, nonce: {nonce}"); + return new KiwiFlareChallengeSolutionModel + { + Nonce = nonce, + Salt = challenge.Salt + }; } - - return new KiwiFlareChallengeSolutionModel - { - Nonce = nonce, - Salt = challenge.Salt - }; } public async Task SolveChallenge(KiwiFlareChallengeModel challenge) { + var start = DateTime.UtcNow; var worker = Task.Run(() => ChallengeWorker(challenge), _ctx); try { @@ -115,6 +114,7 @@ public class KiwiFlare(string kfDomain, string? proxy = null, CancellationToken? throw new Exception("Challenge worker faulted"); } + _logger.Debug($"Worker solved the challenge after {(DateTime.UtcNow - start).TotalMilliseconds} ms"); return worker.Result; } @@ -127,7 +127,7 @@ public class KiwiFlare(string kfDomain, string? proxy = null, CancellationToken? new("b", solution.Nonce.ToString()) }); - var response = await client.PostAsync($"https://{_kfDomain}/.sssg/api/answer", formData, _ctx); + var response = await client.PostAsync($"https://{kfDomain}/.sssg/api/answer", formData, _ctx); var json = await response.Content.ReadFromJsonAsync(_ctx); if (json.TryGetProperty("error", out var error)) { @@ -153,7 +153,7 @@ public class KiwiFlare(string kfDomain, string? proxy = null, CancellationToken? new("f", authToken), }); - var response = await client.PostAsync($"https://{_kfDomain}/.sssg/api/check", formData, _ctx); + var response = await client.PostAsync($"https://{kfDomain}/.sssg/api/check", formData, _ctx); var json = await response.Content.ReadFromJsonAsync(_ctx); if (json.TryGetProperty("error", out var error)) { @@ -161,7 +161,7 @@ public class KiwiFlare(string kfDomain, string? proxy = null, CancellationToken? return false; } - if (json.TryGetProperty("auth", out var auth)) + if (json.TryGetProperty("auth", out _)) { return true; }