public static void OutputKey(RSAWrapper rsa) { ProgramParameters parms = ProgramParameters.Instance; Console.WriteLine(); Console.WriteLine("Ding!! Delicious scallions for you!!"); Console.WriteLine(); if (parms.KeyOutputPath != null) { System.IO.File.AppendAllText(parms.KeyOutputPath, "Generated at: " + System.DateTime.Now.ToString("G") + "\n"); System.IO.File.AppendAllText(parms.KeyOutputPath, "Address/Hash: " + rsa.OnionHash + ".onion\n"); System.IO.File.AppendAllText(parms.KeyOutputPath, "Public Modulus: " + rsa.Rsa.PublicModulus.ToDecimalString() + "\n"); System.IO.File.AppendAllText(parms.KeyOutputPath, "Public Exponent: " + rsa.Rsa.PublicExponent.ToDecimalString() + "\n"); if (rsa.HasPrivateKey) { System.IO.File.AppendAllText(parms.KeyOutputPath, "RSA key: \n" + rsa.Rsa.PrivateKeyAsPEM + "\n"); } System.IO.File.AppendAllText(parms.KeyOutputPath, "\n\n"); } Console.WriteLine("Public Modulus: {0}", rsa.Rsa.PublicModulus.ToDecimalString()); Console.WriteLine("Public Exponent: {0}", rsa.Rsa.PublicExponent.ToDecimalString()); Console.WriteLine("Address/Hash: " + rsa.OnionHash + ".onion"); Console.WriteLine(); if (rsa.HasPrivateKey) { Console.WriteLine(rsa.Rsa.PrivateKeyAsPEM); Console.WriteLine(); } }
public static void WriteModuli() { ProgramParameters parms = ProgramParameters.Instance; var rp = new RegexPattern(parms.Regex); ulong hashes_per_win = (ulong)(0.5 / rp.GenerateAllOnionPatternsForRegex().Select(t => Math.Pow(2, -5 * t.Count(q => q != '.'))).Sum()); ulong hashes_per_key = (CLRuntime.EXP_MAX - CLRuntime.EXP_MIN) / 2; ulong keys_needed = hashes_per_win / hashes_per_key; uint SF = 5; Console.WriteLine("Generating that pattern will require approximately {0:0.000} gigahashes.", hashes_per_win / 1e9); Console.WriteLine("That will require on average {0} public keys.", keys_needed); Console.WriteLine("Generating {0} keys (for safety's sake).", keys_needed * SF); RSAWrapper rsa = new RSAWrapper(); StreamWriter priv_sw = new StreamWriter(parms.RSAModuliPath + ".priv"); StreamWriter pub_sw = new StreamWriter(parms.RSAModuliPath); for (ulong i = 0; i < keys_needed * SF; i++) { if (i % 100 == 0) { Console.WriteLine("Generating key {0} of {1}...", i, keys_needed * SF); } rsa.GenerateKey((int)parms.KeySize); pub_sw.WriteLine(rsa.Rsa.PublicModulus.ToDecimalString()); priv_sw.WriteLine("Public Modulus: " + rsa.Rsa.PublicModulus.ToDecimalString()); priv_sw.WriteLine(rsa.Rsa.PrivateKeyAsPEM); priv_sw.WriteLine(""); } pub_sw.Close(); priv_sw.Close(); }
public static string GenerateKernel(ProgramParameters programParameters, int numberOfMasks, int numberOfHashesPerKey, uint[] Bitmask, uint[] Pattern, int numberOfPatterns) { //Read kernel.cl StringBuilder builder = new StringBuilder(); string kernelFile = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + Path.DirectorySeparatorChar + "kernel.cl"; builder.Append(File.ReadAllText(kernelFile)); //Replace program parms builder.Replace("GENERATED__CONSTANTS", programParameters.CreateDefinesString()); //replace checking code builder.Replace("GENERATED__CHECKING_CODE", GenerateCheckingCode(numberOfMasks, numberOfHashesPerKey, Bitmask, Pattern, numberOfPatterns)); //Return generated kernel return builder.ToString(); }
public static string GenerateKernel(ProgramParameters programParameters, int numberOfMasks, int numberOfHashesPerKey, uint[] Bitmask, uint[] Pattern, int numberOfPatterns) { //Read kernel.cl StringBuilder builder = new StringBuilder(); string kernelFile = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + Path.DirectorySeparatorChar + "kernel.cl"; builder.Append(File.ReadAllText(kernelFile)); //Replace program parms builder.Replace("GENERATED__CONSTANTS", programParameters.CreateDefinesString()); //replace checking code builder.Replace("GENERATED__CHECKING_CODE", GenerateCheckingCode(numberOfMasks, numberOfHashesPerKey, Bitmask, Pattern, numberOfPatterns)); //Return generated kernel return(builder.ToString()); }
static void Shutdown() { ProgramParameters parms = ProgramParameters.Instance; if (parms.UsedModuliFile != null) { parms.UsedModuliFile.Close(); } if (parms.PIDFile != null && File.Exists(parms.PIDFile)) { File.Delete(parms.PIDFile); } Console.WriteLine(); Console.WriteLine("Stopping the GPU and shutting down..."); Console.WriteLine(); lock (_runtime) { _runtime.Abort = true; } }
static void Main(string[] args) { ProgramParameters parms = ProgramParameters.Instance; Func <Mode, Action <string> > parseMode = (m) => (s) => { if (!string.IsNullOrEmpty(s)) { parms.ProgramMode = m; } }; OptionSet p = new OptionSet() .Add <uint>("k|keysize=", "Specifies keysize for the RSA key", (i) => parms.KeySize = i) .Add("n|nonoptimized", "Runs non-optimized kernel", parseMode(Mode.NonOptimized)) .Add("l|listdevices", "Lists the devices that can be used.", parseMode(Mode.ListDevices)) .Add("h|?|help", "Displays command line usage help.", parseMode(Mode.Help)) .Add <uint>("d|device=", "Specifies the opencl device that should be used.", (i) => parms.DeviceId = i) .Add <uint>("g|groupsize=", "Specifies the number of threads in a workgroup.", (i) => parms.WorkGroupSize = i) .Add <uint>("w|worksize=", "Specifies the number of hashes preformed at one time.", (i) => parms.WorkSize = i) .Add <uint>("t|cputhreads=", "Specifies the number of CPU threads to use when creating work. (EXPERIMENTAL - OpenSSL not thread-safe)", (i) => parms.CpuThreads = i) .Add <string>("p|save-kernel=", "Saves the generated kernel to this path.", (i) => parms.SaveGeneratedKernelPath = i) .Add <string>("o|output=", "Saves the generated key(s) and address(es) to this path.", (i) => parms.KeyOutputPath = i) .Add("c|continue", "Continue to search for keys rather than exiting when a key is found.", (i) => { if (!string.IsNullOrEmpty(i)) { parms.ContinueGeneration = true; } }) ; List <string> extra = p.Parse(args); if (parms.ProgramMode == Mode.NonOptimized || parms.ProgramMode == Mode.Normal) { if (extra.Count < 1) { parms.ProgramMode = Mode.Help; } else { parms.Regex = extra.ToDelimitedString("|"); } } //_runtime.Run(ProgramParameters.Instance,"prefix[abcdef]"); switch (parms.ProgramMode) { case Mode.Help: Help(p); break; case Mode.ListDevices: ListDevices(); break; case Mode.Normal: case Mode.NonOptimized: { // If no Work Group Size provided, then query the selected device for preferred, if not found set to 32. if (parms.WorkGroupSize == 0) { ulong preferredWorkGroupSize = 32; uint deviceId = 0; foreach (CLDeviceInfo device in CLRuntime.GetDevices()) { if (!device.CompilerAvailable) { continue; } if (deviceId == parms.DeviceId) { preferredWorkGroupSize = getPreferredWorkGroupSize(device.DeviceId); break; } deviceId++; } parms.WorkGroupSize = (uint)preferredWorkGroupSize; } Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress); _runtime.Run(ProgramParameters.Instance); } break; } }
public void Run(ProgramParameters parms) //int deviceId, int workGroupSize, int workSize, int numThreadsCreateWork, KernelType kernelt, int keysize, IEnumerable<string> patterns) { int deviceId = (int)parms.DeviceId; int workGroupSize = (int)parms.WorkGroupSize; int workSize = (int)parms.WorkSize; int numThreadsCreateWork = (int)parms.CpuThreads; KernelType kernelt = parms.KernelType; int keysize = (int)parms.KeySize; Console.WriteLine("Cooking up some delicions scallions..."); this.workSize = (uint)workSize; profiler = new Profiler(); #region init profiler.StartRegion("init"); // Combine patterns into a single regexp and build one of Richard's objects var rp = new RegexPattern(parms.Regex); // Create bitmasks array for the GPU var gpu_bitmasks = rp.GenerateOnionPatternBitmasksForGpu(MIN_CHARS) .Select(t => TorBase32.ToUIntArray(TorBase32.CreateBase32Mask(t))) .SelectMany(t => t).ToArray(); //Create Hash Table uint[] dataArray; ushort[] hashTable; uint[][] all_patterns; int max_items_per_key = 0; { Func <uint[], ushort> fnv = (pattern_arr) => { uint f = Util.FNVHash(pattern_arr[0], pattern_arr[1], pattern_arr[2]); f = ((f >> 10) ^ f) & (uint)1023; return((ushort)f); }; all_patterns = rp.GenerateOnionPatternsForGpu(7) .Select(i => TorBase32.ToUIntArray(TorBase32.FromBase32Str(i.Replace('.', 'a')))) .ToArray(); var gpu_dict_list = all_patterns .Select(i => new KeyValuePair <ushort, uint>(fnv(i), Util.FNVHash(i[0], i[1], i[2]))) .GroupBy(i => i.Key) .OrderBy(i => i.Key) .ToList(); dataArray = gpu_dict_list.SelectMany(i => i.Select(j => j.Value)).ToArray(); hashTable = new ushort[1024]; //item 1 index, item 2 length int currIndex = 0; foreach (var item in gpu_dict_list) { int len = item.Count(); hashTable[item.Key] = (ushort)currIndex; currIndex += len; if (len > max_items_per_key) { max_items_per_key = len; } } Console.WriteLine("Putting {0} patterns into {1} buckets.", currIndex, gpu_dict_list.Count); } // Set the key size keySize = keysize; // Find kernel name and check key size kernel_type = kernelt; string kernelFileName = null, kernelName = null; switch (kernel_type) { case KernelType.Normal: kernelFileName = "kernel.cl"; kernelName = "normal"; break; case KernelType.Optimized4_9: if (keySize != 1024) { throw new ArgumentException("Kernel only works with keysize 1024."); } kernelFileName = "kernel.cl"; kernelName = "optimized"; break; case KernelType.Optimized4_11: if (keySize != 2048 && keySize != 4096) { throw new ArgumentException("Kernel only works with keysize 2048 or 4096."); } kernelFileName = "kernel.cl"; kernelName = "optimized"; break; default: throw new ArgumentException("Pick a supported kernel."); } Console.WriteLine("Using kernel {0} from file {1} ({2})", kernelName, kernelFileName, kernel_type); //create device context and kernel CLDeviceInfo device = GetDevices()[deviceId]; if ((uint)workGroupSize > device.MaxWorkGroupSize) { workGroupSize = (int)device.MaxWorkGroupSize; } Console.WriteLine("Using work group size {0}", workGroupSize); CLContext context = new CLContext(device.DeviceId); Console.Write("Compiling kernel... "); string kernel_text = KernelGenerator.GenerateKernel(parms, gpu_bitmasks.Length / 3, max_items_per_key, gpu_bitmasks.Take(3).ToArray(), all_patterns[0], all_patterns.Length); if (parms.SaveGeneratedKernelPath != null) { System.IO.File.WriteAllText(parms.SaveGeneratedKernelPath, kernel_text); } IntPtr program = context.CreateAndCompileProgram(kernel_text); var hashes_per_win = 0.5 / rp.GenerateAllOnionPatternsForRegex().Select(t => Math.Pow(2, -5 * t.Count(q => q != '.'))).Sum(); Console.WriteLine("done."); CLKernel kernel = context.CreateKernel(program, kernelName); //Create buffers CLBuffer <uint> bufLastWs; CLBuffer <uint> bufMidstates; CLBuffer <int> bufExpIndexes; CLBuffer <uint> bufResults; { int num_exps = (get_der_len(EXP_MAX) - get_der_len(EXP_MIN) + 1); uint[] LastWs = new uint[num_exps * 16]; uint[] Midstates = new uint[num_exps * 5]; int[] ExpIndexes = new int[num_exps]; uint[] Results = new uint[128]; bufLastWs = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadOnly | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, LastWs); bufMidstates = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadOnly | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, Midstates); bufExpIndexes = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadOnly | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, ExpIndexes); bufResults = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadWrite | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, Results); } //Create pattern buffers CLBuffer <ushort> bufHashTable; CLBuffer <uint> bufDataArray; CLBuffer <uint> bufBitmasks; { bufHashTable = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadOnly | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, hashTable); bufDataArray = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadOnly | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, dataArray); bufBitmasks = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadOnly | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, gpu_bitmasks); } //Set kernel arguments lock (new object()) { } // Empty lock, resolves (or maybe hides) a race condition in SetKernelArg kernel.SetKernelArg(0, bufLastWs); kernel.SetKernelArg(1, bufMidstates); kernel.SetKernelArg(2, bufResults); kernel.SetKernelArg(3, (uint)EXP_MIN); kernel.SetKernelArg(4, (byte)get_der_len(EXP_MIN)); kernel.SetKernelArg(5, bufExpIndexes); kernel.SetKernelArg(6, bufBitmasks); kernel.SetKernelArg(7, bufHashTable); kernel.SetKernelArg(8, bufDataArray); profiler.EndRegion("init"); bufBitmasks.EnqueueWrite(true); bufHashTable.EnqueueWrite(true); bufDataArray.EnqueueWrite(true); //start the thread to generate input data for (int i = 0; i < numThreadsCreateWork; i++) { Thread inputThread = new Thread(CreateInput); inputThread.Start(); inputThreads.Add(inputThread); } Thread.Sleep(3000); //wait just a bit so some work is available #endregion int loop = 0; var gpu_runtime_sw = System.Diagnostics.Stopwatch.StartNew(); profiler.StartRegion("total without init"); bool success = false; while (!success) { lock (this) { if (this.Abort) { break; } } //abort flag was set.... bail KernelInput input = null; lock (_kernelInput) { if (_kernelInput.Count > 0) { input = _kernelInput.Pop(); } } if (input == null) //If we have run out of work sleep for a bit { Console.WriteLine("Lack of work for the GPU!! Taking a nap!!"); Thread.Sleep(250); continue; } profiler.StartRegion("set buffers"); bufLastWs.Data = input.LastWs; bufMidstates.Data = input.Midstates; bufExpIndexes.Data = input.ExpIndexes; bufResults.Data = input.Results; kernel.SetKernelArg(3, input.BaseExp); profiler.EndRegion("set buffers"); profiler.StartRegion("write buffers"); bufLastWs.EnqueueWrite(true); bufMidstates.EnqueueWrite(true); bufExpIndexes.EnqueueWrite(true); Array.Clear(bufResults.Data, 0, bufResults.Data.Length); bufResults.EnqueueWrite(true); profiler.EndRegion("write buffers"); kernel.EnqueueNDRangeKernel(workSize, workGroupSize); profiler.StartRegion("read results"); bufResults.EnqueueRead(false); profiler.EndRegion("read results"); loop++; Console.Write("\r"); long hashes = (long)workSize * (long)loop; Console.Write("LoopIteration:{0} HashCount:{1:0.00}MH Speed:{2:0.0}MH/s Runtime:{3} Predicted:{4} ", loop, hashes / 1000000.0d, hashes / gpu_runtime_sw.ElapsedMilliseconds / 1000.0d, gpu_runtime_sw.Elapsed.ToString().Split('.')[0], PredictedRuntime(hashes_per_win, hashes * 1000 / gpu_runtime_sw.ElapsedMilliseconds)); profiler.StartRegion("check results"); foreach (var result in input.Results) { if (result != 0) { try { input.Rsa.ChangePublicExponent((BigNumber)result); string onion_hash = input.Rsa.OnionHash; Console.WriteLine("CPU checking hash: {0}", onion_hash); if (rp.DoesOnionHashMatchPattern(onion_hash)) { Console.WriteLine(); Console.WriteLine("Ding!! Delicious scallions for you!!"); Console.WriteLine(); string key = input.Rsa.Rsa.PrivateKeyAsPEM; if (parms.KeyOutputPath != null) { System.IO.File.AppendAllText(parms.KeyOutputPath, "Generated at: " + System.DateTime.Now.ToString("G") + "\n"); System.IO.File.AppendAllText(parms.KeyOutputPath, "Address/Hash: " + onion_hash + ".onion\n"); System.IO.File.AppendAllText(parms.KeyOutputPath, "RSA key: \n" + key + "\n\n"); } Console.WriteLine("Exponent: {0}", result); input.Rsa.ChangePublicExponent((BigNumber)result); Console.WriteLine("Address/Hash: " + onion_hash + ".onion"); Console.WriteLine(); Console.WriteLine(key); Console.WriteLine(); if (!parms.ContinueGeneration) { success = true; } } } catch (OpenSslException /*ex*/) { } } } profiler.EndRegion("check results"); } foreach (var thread in inputThreads) { thread.Abort(); } profiler.EndRegion("total without init"); Console.WriteLine(profiler.GetSummaryString()); Console.WriteLine("{0:0.00} million hashes per second", ((long)loop * (long)workSize * (long)1000) / (double)profiler.GetTotalMS("total without init") / (double)1000000); }
public void Run(ProgramParameters parms) //int deviceId, int workGroupSize, int workSize, int numThreadsCreateWork, KernelType kernelt, int keysize, IEnumerable<string> patterns) { int deviceId = (int)parms.DeviceId; int workGroupSize = (int)parms.WorkGroupSize; int workSize = (int)parms.WorkSize; int numThreadsCreateWork = (int)parms.CpuThreads; KernelType kernelt = parms.KernelType; int keysize = (int)parms.KeySize; Console.WriteLine("Cooking up some delicions scallions..."); this.workSize = (uint)workSize; profiler = new Profiler(); #region init profiler.StartRegion("init"); // Combine patterns into a single regexp and build one of Richard's objects var rp = new RegexPattern(parms.Regex); // Create bitmasks array for the GPU var gpu_bitmasks = rp.GenerateOnionPatternBitmasksForGpu(MIN_CHARS) .Select(t => TorBase32.ToUIntArray(TorBase32.CreateBase32Mask(t))) .SelectMany(t => t).ToArray(); //Create Hash Table uint[] dataArray; ushort[] hashTable; uint[][] all_patterns; int max_items_per_key = 0; { Func <uint[], ushort> fnv = (pattern_arr) => { uint f = Util.FNVHash(pattern_arr[0], pattern_arr[1], pattern_arr[2]); f = ((f >> 10) ^ f) & (uint)1023; return((ushort)f); }; all_patterns = rp.GenerateOnionPatternsForGpu(7) .Select(i => TorBase32.ToUIntArray(TorBase32.FromBase32Str(i.Replace('.', 'a')))) .ToArray(); var gpu_dict_list = all_patterns .Select(i => new KeyValuePair <ushort, uint>(fnv(i), Util.FNVHash(i[0], i[1], i[2]))) .GroupBy(i => i.Key) .OrderBy(i => i.Key) .ToList(); dataArray = gpu_dict_list.SelectMany(i => i.Select(j => j.Value)).ToArray(); hashTable = new ushort[1024]; //item 1 index, item 2 length int currIndex = 0; foreach (var item in gpu_dict_list) { int len = item.Count(); hashTable[item.Key] = (ushort)currIndex; currIndex += len; if (len > max_items_per_key) { max_items_per_key = len; } } Console.WriteLine("Putting {0} patterns into {1} buckets.", currIndex, gpu_dict_list.Count); } // Set the key size keySize = keysize; // Find kernel name and check key size kernel_type = kernelt; string kernelFileName = null, kernelName = null; switch (kernel_type) { case KernelType.Normal: kernelFileName = "kernel.cl"; kernelName = "normal"; break; case KernelType.Optimized4: kernelFileName = "kernel.cl"; kernelName = "optimized"; break; default: throw new ArgumentException("Pick a supported kernel."); } Console.WriteLine("Using kernel {0} from file {1} ({2})", kernelName, kernelFileName, kernel_type); //create device context and kernel CLDeviceInfo device = GetDevices()[deviceId]; if ((uint)workGroupSize > device.MaxWorkGroupSize) { workGroupSize = (int)device.MaxWorkGroupSize; } Console.WriteLine("Using work group size {0}", workGroupSize); CLContext context = new CLContext(device.DeviceId); Console.Write("Compiling kernel... "); string kernel_text = KernelGenerator.GenerateKernel(parms, gpu_bitmasks.Length / 3, max_items_per_key, gpu_bitmasks.Take(3).ToArray(), all_patterns[0], all_patterns.Length, parms.ExponentIndex); if (parms.SaveGeneratedKernelPath != null) { System.IO.File.WriteAllText(parms.SaveGeneratedKernelPath, kernel_text); } IntPtr program = context.CreateAndCompileProgram(kernel_text); var hashes_per_win = 0.5 / rp.GenerateAllOnionPatternsForRegex().Select(t => Math.Pow(2, -5 * t.Count(q => q != '.'))).Sum(); Console.WriteLine("done."); // // Test SHA1 algo // { Console.WriteLine("Testing SHA1 hash..."); CLKernel shaTestKern = context.CreateKernel(program, "shaTest"); CLBuffer <uint> bufSuccess = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadWrite | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, new uint[5]); shaTestKern.SetKernelArg(0, bufSuccess); shaTestKern.EnqueueNDRangeKernel(workSize, workGroupSize); bufSuccess.EnqueueRead(false); // Calculate the SHA1 CPU-side System.Security.Cryptography.SHA1 sha = new System.Security.Cryptography.SHA1CryptoServiceProvider(); String testdata = "Hello world!"; byte[] cpuhash = sha.ComputeHash(Encoding.ASCII.GetBytes(testdata)); StringBuilder cpuhex = new StringBuilder(cpuhash.Length * 2); foreach (byte b in cpuhash) { cpuhex.AppendFormat("{0:x2}", b); } Console.WriteLine("CPU SHA-1: {0}", cpuhex.ToString()); // Convert the SHA1 GPU-side to hex String gpuhex = String.Format("{0:x8}{1:x8}{2:x8}{3:x8}{4:x8}", bufSuccess.Data[0], bufSuccess.Data[1], bufSuccess.Data[2], bufSuccess.Data[3], bufSuccess.Data[4]); Console.WriteLine("GPU SHA-1: {0}", gpuhex); if (gpuhex != cpuhex.ToString()) { Console.WriteLine(); Console.WriteLine("******************************* ERROR ERROR ERROR *******************************"); Console.WriteLine("* *"); Console.WriteLine("* GPU and CPU SHA-1 calculations do NOT match. *"); Console.WriteLine("* Hashing will NOT work until this is resolved. *"); Console.WriteLine("* The program will continue, but WILL NOT find a valid match. *"); Console.WriteLine("* *"); Console.WriteLine("* See https://github.com/lachesis/scallion/issues/11#issuecomment-29046835 *"); Console.WriteLine("* *"); Console.WriteLine("*********************************************************************************"); Console.WriteLine(); } else { Console.WriteLine("Looks good!"); } } CLKernel kernel = context.CreateKernel(program, kernelName); //Create buffers CLBuffer <uint> bufLastWs; CLBuffer <uint> bufMidstates; CLBuffer <int> bufExpIndexes; CLBuffer <uint> bufResults; { int num_exps = (get_der_len(EXP_MAX) - get_der_len(EXP_MIN) + 1); uint[] LastWs = new uint[num_exps * 16]; uint[] Midstates = new uint[num_exps * 5]; int[] ExpIndexes = new int[num_exps]; uint[] Results = new uint[128]; bufLastWs = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadOnly | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, LastWs); bufMidstates = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadOnly | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, Midstates); bufExpIndexes = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadOnly | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, ExpIndexes); bufResults = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadWrite | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, Results); } //Create pattern buffers CLBuffer <ushort> bufHashTable; CLBuffer <uint> bufDataArray; CLBuffer <uint> bufBitmasks; { bufHashTable = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadOnly | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, hashTable); bufDataArray = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadOnly | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, dataArray); bufBitmasks = context.CreateBuffer(OpenTK.Compute.CL10.MemFlags.MemReadOnly | OpenTK.Compute.CL10.MemFlags.MemCopyHostPtr, gpu_bitmasks); } //Set kernel arguments lock (new object()) { } // Empty lock, resolves (or maybe hides) a race condition in SetKernelArg kernel.SetKernelArg(0, bufLastWs); kernel.SetKernelArg(1, bufMidstates); kernel.SetKernelArg(2, bufResults); kernel.SetKernelArg(3, (uint)EXP_MIN); kernel.SetKernelArg(4, (byte)get_der_len(EXP_MIN)); kernel.SetKernelArg(5, bufExpIndexes); kernel.SetKernelArg(6, bufBitmasks); kernel.SetKernelArg(7, bufHashTable); kernel.SetKernelArg(8, bufDataArray); profiler.EndRegion("init"); bufBitmasks.EnqueueWrite(true); bufHashTable.EnqueueWrite(true); bufDataArray.EnqueueWrite(true); //start the thread to generate input data for (int i = 0; i < numThreadsCreateWork; i++) { Thread inputThread = new Thread(CreateInput); inputThread.Start(); inputThreads.Add(inputThread); } Thread.Sleep(3000); //wait just a bit so some work is available #endregion int loop = 0; var gpu_runtime_sw = System.Diagnostics.Stopwatch.StartNew(); profiler.StartRegion("total without init"); bool success = false; while (!success) { lock (this) { if (this.Abort) { break; } } //abort flag was set.... bail KernelInput input = null; lock (_kernelInput) { if (_kernelInput.Count > 0) { input = _kernelInput.Pop(); } } if (input == null) //If we have run out of work sleep for a bit { Console.WriteLine("Lack of work for the GPU!! Taking a nap!!"); Thread.Sleep(250); continue; } profiler.StartRegion("set buffers"); bufLastWs.Data = input.LastWs; bufMidstates.Data = input.Midstates; bufExpIndexes.Data = input.ExpIndexes; bufResults.Data = input.Results; kernel.SetKernelArg(3, input.BaseExp); profiler.EndRegion("set buffers"); profiler.StartRegion("write buffers"); bufLastWs.EnqueueWrite(true); bufMidstates.EnqueueWrite(true); bufExpIndexes.EnqueueWrite(true); Array.Clear(bufResults.Data, 0, bufResults.Data.Length); bufResults.EnqueueWrite(true); profiler.EndRegion("write buffers"); kernel.EnqueueNDRangeKernel(workSize, workGroupSize); profiler.StartRegion("read results"); bufResults.EnqueueRead(false); profiler.EndRegion("read results"); loop++; Console.Write("\r"); long hashes = (long)workSize * (long)loop; Console.Write("LoopIteration:{0} HashCount:{1:0.00}MH Speed:{2:0.0}MH/s Runtime:{3} Predicted:{4} ", loop, hashes / 1000000.0d, hashes / gpu_runtime_sw.ElapsedMilliseconds / 1000.0d, gpu_runtime_sw.Elapsed.ToString().Split('.')[0], PredictedRuntime(hashes_per_win, hashes * 1000 / gpu_runtime_sw.ElapsedMilliseconds)); profiler.StartRegion("check results"); foreach (var result in input.Results) { if (result != 0) { try { input.Rsa.Rsa.PublicExponent = (BigNumber)result; string onion_hash = input.Rsa.OnionHash; Console.WriteLine("CPU checking hash: {0}", onion_hash); if (rp.DoesOnionHashMatchPattern(onion_hash)) { input.Rsa.ChangePublicExponent(result); OutputKey(input.Rsa); if (!parms.ContinueGeneration) { success = true; } } } catch (OpenSslException /*ex*/) { } } } profiler.EndRegion("check results"); // Mark key as used (if configured) if (parms.UsedModuliFile != null) { parms.UsedModuliFile.WriteLine(input.Rsa.Rsa.PublicModulus.ToDecimalString()); } } foreach (var thread in inputThreads) { thread.Abort(); } profiler.EndRegion("total without init"); Console.WriteLine(profiler.GetSummaryString()); Console.WriteLine("{0:0.00} million hashes per second", ((long)loop * (long)workSize * (long)1000) / (double)profiler.GetTotalMS("total without init") / (double)1000000); }
private void CreateInput() { ProgramParameters parms = ProgramParameters.Instance; while (true) { bool inputQueueIsLow = false; lock (_kernelInput) { inputQueueIsLow = _kernelInput.Count < 300; } if (inputQueueIsLow) { int num_exps = (get_der_len(EXP_MAX) - get_der_len(EXP_MIN) + 1); KernelInput input = new KernelInput(num_exps); // Read moduli from file or generate them if possible if (parms.RSAPublicModuli != null) { if (parms.RSAPublicModuli.Count > 0) { input.Rsa.Rsa.PublicModulus = parms.RSAPublicModuli.Dequeue(); } else { break; } } else { profiler.StartRegion("generate key"); input.Rsa.GenerateKey(keySize); // Generate a key profiler.EndRegion("generate key"); } // Build DERs and calculate midstates for exponents of representitive lengths profiler.StartRegion("cpu precompute"); int cur_exp_num = 0; BigNumber[] Exps = new BigNumber[num_exps]; bool skip_flag = false; // With EXP_MIN = 0x01010001 and EXP_MAX = 0x7FFFFFFF, only one iteration (i = 4) for (int i = get_der_len(EXP_MIN); i <= get_der_len(EXP_MAX); i++) { // With i = 4, exp = 0x01000000 (just a placeholder in the DER) ulong exp = (ulong)0x01 << (int)((i - 1) * 8); // Set the exponent in the RSA key // NO SANITY CHECK - just for building a DER input.Rsa.Rsa.PublicExponent = (BigNumber)exp; Exps[cur_exp_num] = (BigNumber)exp; // Get the DER byte[] der = input.Rsa.DER; int exp_index = der.Length % 64 - i; if (exp_index != parms.ExponentIndex) { Console.WriteLine("Exponent index doesn't match - skipping key"); skip_flag = true; break; } if (i != 4) // exponent length assumed to be 4 in the kernel { Console.WriteLine("Exponent length doesn't match - skipping key"); skip_flag = true; break; } // Put the DER into Ws SHA1 Sha1 = new SHA1(); List <uint[]> Ws = Sha1.DataToPaddedBlocks(der); // Put all but the last block through the hash Ws.Take(Ws.Count - 1).Select((t) => { Sha1.SHA1_Block(t); return(t); }).ToArray(); // Put the midstate, the last W block, and the byte index of the exponent into the CL buffers Sha1.H.CopyTo(input.Midstates, 5 * cur_exp_num); Ws.Last().Take(16).ToArray().CopyTo(input.LastWs, 16 * cur_exp_num); input.ExpIndexes[cur_exp_num] = exp_index; // Increment the current exponent size cur_exp_num++; break; } profiler.EndRegion("cpu precompute"); if (skip_flag) { continue; // we got a bad key - don't enqueue it } List <KernelInput> inputs = new List <KernelInput>(); inputs.Add(input); for (uint i = 1; i < (EXP_MAX - EXP_MIN) / 2 / workSize - 1; i++) { //profiler.StartRegion("generate key"); if (EXP_MIN + workSize * 2 * i >= EXP_MAX) { throw new ArgumentException("base_exp > EXP_MAX"); } inputs.Add(new KernelInput(input, EXP_MIN + workSize * 2 * i)); //profiler.EndRegion("generate key"); } lock (_kernelInput) //put input on queue { foreach (KernelInput i in inputs) { _kernelInput.Push(i); } } continue; //skip the sleep cause we might be really low } Thread.Sleep(50); } }
static void Main(string[] args) { ProgramParameters parms = ProgramParameters.Instance; Func <Mode, Action <string> > parseMode = (m) => (s) => { if (!string.IsNullOrEmpty(s)) { parms.ProgramMode = m; } }; OptionSet p = new OptionSet() .Add <uint>("k|keysize=", "Specifies keysize for the RSA key", (i) => parms.KeySize = i) .Add("n|nonoptimized", "Runs non-optimized kernel", parseMode(Mode.NonOptimized)) .Add("l|listdevices", "Lists the devices that can be used.", parseMode(Mode.ListDevices)) .Add("h|?|help", "Displays command line usage help.", parseMode(Mode.Help)) .Add <uint>("d|device=", "Specifies the opencl device that should be used.", (i) => parms.DeviceId = i) .Add <uint>("g|groupsize=", "Specifies the number of threads in a workgroup.", (i) => parms.WorkGroupSize = i) .Add <uint>("w|worksize=", "Specifies the number of hashes preformed at one time.", (i) => parms.WorkSize = i) .Add <uint>("t|cputhreads=", "Specifies the number of CPU threads to use when creating work. (EXPERIMENTAL - OpenSSL not thread-safe)", (i) => parms.CpuThreads = i) .Add <string>("pidfile=", "Specifies a file where the process id will be written; file will be deleted at exit", (i) => parms.PIDFile = i) .Add <string>("m|modulifile=", "Specifies a file containing public key moduli", (i) => parms.RSAModuliPath = i) .Add("s|write-moduli", "Writes moduli and private keys for a given pattern to the file specified with -m", (i) => { if (parms.ProgramMode != Mode.Help) { parms.ProgramMode = Mode.WriteModuli; } }) .Add("r|read-results=", "Reads a results file (generated by a remote miner) and output the winning key (-m must be specified)", (i) => parms.InputResultsPath = i) .Add <string>("p|save-kernel=", "Saves the generated kernel to this path.", (i) => parms.SaveGeneratedKernelPath = i) .Add <string>("o|output=", "Saves the generated key(s) and address(es) to this path.", (i) => parms.KeyOutputPath = i) .Add("c|continue", "Continue to search for keys rather than exiting when a key is found.", (i) => { if (!string.IsNullOrEmpty(i)) { parms.ContinueGeneration = true; } }) ; List <string> extra = p.Parse(args); if (parms.InputResultsPath != null && parms.ProgramMode != Mode.Help) { parms.ProgramMode = Mode.ReadResults; } if (parms.ProgramMode == Mode.NonOptimized || parms.ProgramMode == Mode.Normal || parms.ProgramMode == Mode.WriteModuli) { if (extra.Count < 1) { parms.ProgramMode = Mode.Help; } else { parms.Regex = extra.ToDelimitedString("|"); } } if (parms.PIDFile != null) { File.WriteAllText(parms.PIDFile, System.Diagnostics.Process.GetCurrentProcess().Id.ToString()); } //_runtime.Run(ProgramParameters.Instance,"prefix[abcdef]"); switch (parms.ProgramMode) { case Mode.Help: Help(p); break; case Mode.ListDevices: ListDevices(); break; case Mode.WriteModuli: WriteModuli(); break; case Mode.ReadResults: ReadResults(); break; case Mode.Normal: case Mode.NonOptimized: { // If no Work Group Size provided, then query the selected device for preferred, if not found set to 32. if (parms.WorkGroupSize == 0) { ulong preferredWorkGroupSize = 32; uint deviceId = 0; foreach (CLDeviceInfo device in CLRuntime.GetDevices()) { if (!device.CompilerAvailable) { continue; } if (deviceId == parms.DeviceId) { preferredWorkGroupSize = getPreferredWorkGroupSize(device.DeviceId); break; } deviceId++; } parms.WorkGroupSize = (uint)preferredWorkGroupSize; } // If a moduli file is specified, read it and create or read a .used file if (parms.RSAModuliPath != null) { if (File.Exists(parms.RSAModuliPath)) { // Read and/or create used file string usedPath = parms.RSAModuliPath + ".used"; HashSet <string> used = null; if (File.Exists(usedPath)) { used = new HashSet <string>(); foreach (var line in File.ReadAllLines(usedPath)) { used.Add(line.Trim()); } } else { File.WriteAllText(usedPath, ""); } // Set up used file to be written later parms.UsedModuliFile = new StreamWriter(usedPath, true); // Read moduli file parms.RSAPublicModuli = new Queue <BigNumber>(); foreach (var line in File.ReadAllLines(parms.RSAModuliPath)) { if (used == null || !used.Contains(line.Trim())) { parms.RSAPublicModuli.Enqueue(BigNumber.FromDecimalString(line.Trim())); } } } } Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress); try { _runtime.Run(ProgramParameters.Instance); } finally { Shutdown(); } } break; } }
public static void ReadResults() { ProgramParameters parms = ProgramParameters.Instance; string rsaPrivFn = parms.RSAModuliPath + ".priv"; if (!File.Exists(rsaPrivFn)) { Console.WriteLine("Error: expecting private key file at {0}.", rsaPrivFn); return; } if (!File.Exists(parms.InputResultsPath)) { Console.WriteLine("Error: expecting results from miner at {0}.", parms.InputResultsPath); return; } // Create a map to hold (public modulus as decimal string) -> (private key as pem) IDictionary <string, string> modulusKeyMap = new Dictionary <string, string>(); // Read the priv key list file string currentModulus = null, currentPEM = null; foreach (string l in File.ReadAllLines(rsaPrivFn)) { string line = l.Trim(); if (line.StartsWith("Public Modulus: ")) { currentModulus = line.Replace("Public Modulus: ", ""); } if (line.StartsWith("-----BEGIN RSA PRIVATE KEY-----")) { currentPEM = ""; } currentPEM += line + "\n"; if (line.StartsWith("-----END RSA PRIVATE KEY-----")) { modulusKeyMap.Add(currentModulus, currentPEM); } } // Read the results file string modulus = null, exponent = null, address = null; foreach (string l in File.ReadAllLines(parms.InputResultsPath)) { //string[] split = l.Trim().Split(":".ToCharArray(), 2); string line = l.Trim(); if (line.StartsWith("Public Modulus: ")) { modulus = line.Replace("Public Modulus: ", ""); } if (line.StartsWith("Public Exponent: ")) { exponent = line.Replace("Public Exponent: ", ""); } if (line.StartsWith("Address/Hash: ")) { address = line.Replace("Address/Hash: ", ""); } if (modulus != null && exponent != null && address != null) { // Find the modulus in the private key map string pem; if (!modulusKeyMap.TryGetValue(modulus, out pem)) { throw new InvalidDataException(String.Format("Modulus {0} is missing from the private key data file.", modulus)); } // Load the PEM into the RSA RSAWrapper rsa = new RSAWrapper(); rsa.FromPrivateKeyPEM(pem); // Verify that modulus matches if (rsa.Rsa.PublicModulus != BigNumber.FromDecimalString(modulus)) { throw new InvalidDataException("Modulus of PEM does not match declared value."); } // Change the public exponent rsa.ChangePublicExponent(BigNumber.FromDecimalString(exponent)); // Check the key's sanity rsa.CheckSanity(); // Verify the hash if (rsa.OnionHash + ".onion" != address) { throw new InvalidDataException("Onion hash of key does not match declared value."); } // Yay the key is good! Output it as required CLRuntime.OutputKey(rsa); modulus = null; exponent = null; address = null; } } }