shallot v0.0.3 from taswebqlseworuhc.onion.
[shallot/rransom.git] / src / thread.c
blob59a4206e7d3639b3d3eb600935f35f372961df40
1 // thread procs for shallot
3 #include "config.h"
5 #include <stdint.h> // OpenBSD needs this included before sys/endian.h
7 #if defined(LINUX_PORT) || defined(OSX) || defined(GENERIC)
8 #include "linux.h"
9 #else
10 #include <sys/param.h> // OpenBSD needs this early on too
11 #include <sys/endian.h>
12 #endif
14 #include "math.h"
15 #include "print.h"
16 #include "error.h"
17 #include "thread.h"
18 #include "defines.h"
19 #include "globals.h"
21 #include <string.h>
22 #include <unistd.h>
23 #include <pthread.h>
24 #include <openssl/rsa.h>
25 #include <openssl/sha.h>
27 void *worker(void *params) { // life cycle of a cracking pthread
28 uint64_t e_be; // storage for our "big endian" version of e
29 uint8_t buf[SHA1_DIGEST_LEN],
30 der[RSA_EXP_DER_LEN + 1], // TODO: is the size of this right?
31 optimum = *(uint8_t*)params;
32 char onion[BASE32_ONIONLEN];
33 SHA_CTX hash, copy;
34 RSA *rsa;
36 if(verbose)
37 printf("Thread entering loop... (ID: 0x%X)\n", (uint32_t)pthread_self());
39 while(!found) {
40 // keys are only generated every so often
41 // every 549,755,781,120 tries by default
42 if(verbose)
43 printf("Generating new key... (ID: 0x%X)\n", (uint32_t)pthread_self());
45 if(optimum)
46 rsa = easygen(RSA_OPTM_BITLEN - RSA_PK_E_LENGTH * 8, RSA_PK_E_LENGTH,
47 der, RSA_OPT_DER_LEN, &hash);
48 else
49 rsa = easygen(RSA_KEYS_BITLEN, RSA_PK_E_LENGTH, der, RSA_EXP_DER_LEN,
50 &hash);
52 if(!rsa) // if key generation fails (no [p]rng seed?)
53 error(X_KEY_GEN_FAILS);
55 uint8_t e_bytes = RSA_PK_E_LENGTH; // number of bytes e occupies
56 uint64_t e = RSA_PK_EXPONENT; // public exponent
57 uint64_t e_byte_thresh;
59 int_pow(2, e_bytes * 8, &e_byte_thresh);
60 e_byte_thresh++;
62 uint8_t *e_ptr = ((uint8_t*)&e_be) + 8 - e_bytes;
64 while((e <= elim) && !found) { // main loop
65 // copy the relevant parts of our already set up context
66 memcpy(&copy, &hash, SHA_REL_CTX_LEN); // 40 bytes here...
67 copy.num = hash.num; // and don't forget the num (9)
69 // convert e to big-endian format
70 e_be = htobe64(e);
72 // compute SHA1 digest (majority of loop time spent here!)
73 SHA1_Update(&copy, e_ptr, e_bytes);
74 SHA1_Final(buf, &copy);
76 base32_onion(onion, buf); // base32 encode SHA1 digest
77 loop++; // keep track of our tries...
79 if(!regexec(regex, onion, 0, 0, 0)) { // check for a match
80 if(verbose)
81 printf("Matching hash found, killing off other threads..."
82 " (ID: 0x%X)\n", (uint32_t)pthread_self());
84 // let our main thread know on which thread to wait
85 lucky_thread = pthread_self();
86 found = 1; // kill off our other threads, asyncronously
88 if(monitor)
89 printf("\n"); // keep our printing pretty!
91 if(!BN_bin2bn(e_ptr, e_bytes, rsa->e)) // store our e in the actual key
92 error(X_BIGNUM_FAILED); // and make sure it got there
94 if(!sane_key(rsa)) // check our key
95 error(X_YOURE_UNLUCKY); // bad key :(
97 if(verbose)
98 printf("Public exponent (e) is 0x%llX.\n", e);
100 print_onion(onion); // print our domain
101 print_prkey(rsa); // and more importantly the key
103 RSA_free(rsa); // free up what's left
105 if(verbose)
106 printf("Thread exiting loop... (ID: 0x%X)\n",
107 (uint32_t)pthread_self());
109 return 0;
112 e += 2; // do *** NOT *** forget this!
114 if(e == e_byte_thresh) { // ASN.1 stuff (hey, it could be worse!)
115 // calculate our new threshold
116 int_pow(2, ++e_bytes * 8, &e_byte_thresh);
117 e_byte_thresh++;
119 if(optimum) {
120 RSA_free(rsa);
121 easygen(RSA_OPTM_BITLEN - e_bytes * 8, e_bytes, der, RSA_OPT_DER_LEN,
122 &hash);
124 if(!rsa)
125 error(X_KEY_GEN_FAILS);
126 } else {
127 // play with our key structure (do not try this at home!)
128 der[RSA_ADD_DER_OFF]++;
129 der[RSA_EXP_DER_LEN - RSA_PK_E_LENGTH - 1]++;
131 // and our prebuilt hash
132 SHA1_Init(&hash); // TODO: move to a function
133 SHA1_Update(&hash, der, RSA_EXP_DER_LEN - RSA_PK_E_LENGTH);
136 e_ptr--; // and move the pointer back
139 RSA_free(rsa);
142 if(verbose)
143 printf("Thread exiting loop... (ID: 0x%X)\n", (uint32_t)pthread_self());
145 return 0;
148 void *monitor_proc(void *unused) {
149 printf("\033[sPlease wait a moment for statistics...");
150 time_t start = time(NULL);
152 for(;;) {
153 fflush(stdout); // make sure it gets printed
154 sleep(20);
156 if(found)
157 return 0;
159 time_t current = time(NULL);
160 time_t elapsed = current - start;
162 if(!elapsed)
163 continue; // be paranoid and avoid divide-by-zero exceptions
165 printf("\033[u\033[KHashes: %-20llu Time: %-10d Speed: %-llu",
166 loop, (int)elapsed, loop / elapsed);
169 return 0; // unreachable code, but prevents warnings (!?)