//https://redd.it/8rx5zi using System; using System.Globalization; using System.Linq; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; using System.Threading; namespace SHAPrefix { class Program { [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] private static extern int memcmp(byte[] b1, byte[] b2, int count); private struct ThreadConfig { public byte[] Prefix; } private static volatile bool Cont = true; private static long Hashes = 0; private static object Lockable = new object(); private static byte[] FoundKey; private static byte[] FoundHash; static void Main(string[] args) { Console.Error.Write("Enter prefix as hexadecimal number [0-9,A-F]: "); var Input = Console.ReadLine(); if (Input.Length % 2 == 0) { byte[] Prefix = new byte[Input.Length / 2]; for (var i = 0; i < Prefix.Length; i++) { Cont &= byte.TryParse(Input.Substring(i * 2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out Prefix[i]); } if (Cont) { if (Prefix.Length > 0 && Prefix.Length < 33) { Thread[] TList = new Thread[1/*Environment.ProcessorCount*/]; for (var i = 0; i < TList.Length; i++) { var T = new Thread(FindPrefix); T.IsBackground = true; T.Priority = ThreadPriority.BelowNormal; T.Name = $"Hash Finder #{i + 1}"; TList[i] = T; T.Start(new ThreadConfig() { Prefix = Prefix }); Console.Error.WriteLine("Started {0}", T.Name); } while (Cont) { if (TList.Any(m => !m.IsAlive)) { Cont = false; } else { lock (Lockable) { Console.SetCursorPosition(0, TList.Length + 1); Console.Error.WriteLine("Hashes generated so far: {0}", Hashes); } Thread.Sleep(500); } } foreach (var T in TList) { T.Join(); } if (FoundKey != null && FoundHash != null) { Console.Clear(); Console.WriteLine("Key : {0}", Encoding.ASCII.GetString(FoundKey)); Console.WriteLine("Prefix: {0}", BitConverter.ToString(Prefix).Replace("-", "")); Console.WriteLine("Hash : {0}", BitConverter.ToString(FoundHash).Replace("-", "")); Console.WriteLine("Check : {0}", Validate(FoundKey, FoundHash)); } Console.Error.WriteLine("Process ended"); } else { Console.Error.WriteLine("Prefix length is invalid"); } } else { Console.Error.WriteLine("Invalid hexadecimal number"); } } else { Console.Error.WriteLine("Invalid Prefix. Hexadecimal numbers have an even number of digits"); } Console.ReadKey(true); } static bool Validate(byte[] Key, byte[] Hash) { using (var Gen = HashAlgorithm.Create("SHA256")) { return Hash != null && Hash.Length == 32 && memcmp(Gen.ComputeHash(Key), Hash, Hash.Length) == 0; } } static void FindPrefix(object o) { var RND = new byte[20]; int StepSize = Environment.ProcessorCount; var Config = (ThreadConfig)o; var Hash = new byte[32]; using (var RNG = RandomNumberGenerator.Create()) { RNG.GetBytes(RND); for (var i = 0; i < RND.Length; i += 2) { var S = RND[i].ToString("X2"); RND[i] = (byte)S[0]; RND[i + 1] = (byte)S[1]; } } using (var Gen = HashAlgorithm.Create("SHA256")) { while (Cont) { Hash = Gen.ComputeHash(RND); ++Hashes; if (memcmp(Hash, Config.Prefix, Config.Prefix.Length) != 0) { for (int i = 19; i >= 0; --i) { ++RND[i]; //Roll over Hexadecimal number if (RND[i] == 0x47 /*G*/) { RND[i] = 0x30 /*0*/; } else { //Skip ASCII Gap between digits and letters if (RND[i] == 0x3A /*:*/) { RND[i] = 0x41 /*A*/; } //Stop incrementing this number break; } } } else { break; } } if (memcmp(Hash, Config.Prefix, Config.Prefix.Length) == 0) { FoundKey = RND; FoundHash = Hash; } } } } }