niceBit.c (8021B)
1 #include "createPubKey.h" 2 #include "walletImportFormat.h" 3 #include <ctype.h> 4 #include <secp256k1.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <time.h> 8 #include <unistd.h> 9 10 #include <unistd.h> 11 12 static secp256k1_context *ctx = NULL; 13 14 /* Create private & public address pair */ 15 int gen_keypair(unsigned char *seckey, char *pubaddress, 16 secp256k1_context *ctx) { 17 secp256k1_pubkey pubkey; 18 unsigned char public_key64[65]; 19 20 size_t pk_len = 65; 21 22 int i = 0; 23 24 /* Load private key (seckey) from random bytes */ 25 FILE *frand = fopen("/dev/urandom", "r"); 26 fread(seckey, 32, 1, frand); 27 fclose(frand); 28 if (frand == NULL) { 29 printf("Failed to read /dev/urandom\n"); 30 return 0; 31 } 32 33 /* Print private key, 34 printf("Seckey : "); 35 for(int i=0; i<32; i++) { 36 printf("%02X", seckey[i]); 37 } 38 printf("\n\n"); 39 */ 40 41 /* Apparently there is a 2^-128 chance of 42 * a secret key being invalid. 43 * https://en.bitcoin.it/wiki/Private_key 44 */ 45 /* Verify secret key is valid */ 46 if (!secp256k1_ec_seckey_verify(ctx, seckey)) { 47 printf("Invalid secret key\n"); 48 } 49 50 /* Create Public Key */ 51 if (!secp256k1_ec_pubkey_create(ctx, &pubkey, seckey)) { 52 printf("Failed to create public key\n"); 53 return 0; 54 } 55 56 /* Serialize Public Key */ 57 secp256k1_ec_pubkey_serialize(ctx, public_key64, &pk_len, &pubkey, 58 SECP256K1_EC_UNCOMPRESSED); 59 60 /* Print public key */ 61 /* 62 printf("Long Public Key : "); 63 for(int i=0; i<65; i++) { 64 printf("%02X", public_key64[i]); 65 } 66 printf("\n\n"); 67 */ 68 69 /* Generate Public Address 70 * (from create_pubkey.h) 71 */ 72 pubkey_to_P2PKH(public_key64, pubaddress); 73 74 return 1; 75 } 76 77 int check_nums(char *pubaddress, int searchlen) { 78 unsigned char compstr[40]; 79 char possibleChars[] = 80 "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; 81 int j; 82 83 /* For each vanity length 84 * ('len' digits in a row) 85 */ 86 for (int len = 10; len >= searchlen; len--) { 87 88 /* For each digit 1-9 */ 89 for (int i = 0; i < 58; i++) { 90 91 /* Comprise compstr of 'len' repeats 92 * of digit 'i' 93 */ 94 j = 0; 95 while (j < len) { 96 compstr[j] = possibleChars[i]; 97 j++; 98 } 99 100 /* End string with null char*/ 101 compstr[j] = '\0'; 102 103 /* Check if string in pubaddress */ 104 if (strstr(pubaddress, compstr) != NULL) { 105 printf("Found : %s\n", compstr); 106 return 1; 107 } 108 } 109 } 110 return 0; 111 } 112 113 int check_words(char *pubaddress, char (*words)[34], int nwords) { 114 for (int i = 0; i < nwords; i++) { 115 /* printf("%s\n", words[i]); 116 puts(pubaddress); */ 117 if (strstr(pubaddress, words[i]) != NULL) { 118 printf("Found : %s\n", words[i]); 119 return 1; 120 } 121 } 122 return 0; 123 } 124 125 int check_vanity(char *pubaddress, int searchlen, char (*words)[34], 126 int nwords) { 127 if ((nwords > 0) && check_words(pubaddress, words, nwords)) { 128 return 1; 129 } 130 if ((searchlen > 0) && check_nums(pubaddress, searchlen)) { 131 return 1; 132 } 133 return 0; 134 } 135 136 void all_substitutes(char (*words)[34], char word[34], int *n_words, int len, 137 int start, int a) { 138 if (start == len) { 139 strcpy(words[*n_words], word); 140 words[*n_words - 1][len] = '\0'; 141 (*n_words)++; 142 return; 143 } 144 char ch = word[start]; 145 char sub = '\0'; 146 switch (ch) { 147 case 'e': 148 if (a == 1) { 149 sub = '3'; 150 } 151 break; 152 case '1': 153 if (a == 1) { 154 sub = 'i'; 155 } 156 break; 157 case 'o': 158 // No base58 sub 159 break; 160 case 'L': 161 // No base58 sub 162 break; 163 case 'i': 164 // No base58 sub 165 break; 166 default: 167 if (ch >= 'a' && ch <= 'z') { 168 sub = toupper(ch); 169 } else if (ch >= 'A' && ch <= 'Z') { 170 sub = tolower(ch); 171 } 172 break; 173 } 174 // Skip on special chars 175 if (sub == '\0') { 176 all_substitutes(words, word, n_words, len, start + 1, a); 177 } else { 178 char word2[34]; 179 strcpy(word2, word); 180 word2[start] = sub; 181 all_substitutes(words, word, n_words, len, start + 1, a); 182 all_substitutes(words, word2, n_words, len, start + 1, a); 183 } 184 } 185 186 void alphanum_combinations(char (*word)[34], char search_list[100000][34], 187 int *n_words, int a) { 188 int initial_n_words = *n_words; 189 *n_words = 0; 190 // Generated alphanumeric substitutions 191 for (int i = 0; i < initial_n_words; i++) { 192 all_substitutes(search_list, word[i], n_words, strlen(word[i]), 0, a); 193 } 194 } 195 196 int main(int argc, char **argv) { 197 unsigned char seckey[32]; 198 char pubaddress[34]; 199 200 char *p = pubaddress; 201 char *n = "0"; 202 char *filename = ""; 203 int C = 0; 204 int a = 0; 205 206 int searchlen; 207 int c; 208 209 long number_of_processors = sysconf(_SC_NPROCESSORS_ONLN); 210 211 /* Get input arguments (length) */ 212 while ((c = getopt(argc, argv, "aCn:f:")) != -1) { 213 switch (c) { 214 case 'n': 215 n = optarg; 216 break; 217 case 'f': 218 filename = optarg; 219 break; 220 case 'a': 221 a = 1; 222 break; 223 case 'C': 224 C = 1; 225 break; 226 case '?': 227 printf("Invalid argument: %c\n", optopt); 228 return 1; 229 } 230 } 231 232 if ((n == "0") && (filename == "")) { 233 puts("Resorting to default search length of 6."); 234 n = "6"; 235 } 236 searchlen = atoi(n); 237 238 ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | 239 SECP256K1_CONTEXT_VERIFY); 240 241 int i = 1; 242 243 time_t start_time, current_time; 244 double time_spent; 245 double rate; 246 247 char words[100][34]; 248 249 // Generated alphanumeric substitutions 250 char search_list[100000][34]; 251 int n_words = 0; 252 /* Load Dictionary File */ 253 if (filename != "") { 254 puts("Loading words..."); 255 FILE *fptr = fopen(filename, "r"); 256 257 while (fgets(words[n_words], 34, fptr)) { 258 words[n_words][strlen(words[n_words]) - 1] = '\0'; 259 puts(words[n_words]); 260 n_words++; 261 } 262 if (C) { 263 alphanum_combinations(words, search_list, &n_words, a); 264 265 for (i = 0; i < n_words; i++) { 266 printf("word %d is %s \n", i, search_list[i]); 267 } 268 269 // search_list[n_words][0] = '\0'; 270 } else { 271 for (i = 0; i < n_words; i++) { 272 strcpy(search_list[i], words[i]); 273 } 274 } 275 printf("%d words have been loaded.\n", n_words); 276 } 277 278 printf("Running on %d processors.\n", number_of_processors); 279 puts("Beginning search...\n"); 280 for (unsigned i = 1; i != number_of_processors; ++i) 281 if (0 == fork()) 282 break; 283 284 time(&start_time); 285 while (1) { 286 if (!gen_keypair(seckey, pubaddress, ctx)) { 287 printf("Failed to create keypair\n"); 288 return 1; 289 } 290 291 if (check_vanity(pubaddress, searchlen, search_list, n_words)) { 292 printf("Private key (raw): "); 293 for (int j = 0; j < 32; j++) { 294 printf("%02X", seckey[j]); 295 } 296 printf("Private key (WIF): "); 297 create_wif(seckey); 298 299 printf("Public Address: %s\n\n", pubaddress); 300 } 301 302 if (i % 100000 == 0) { 303 time(¤t_time); 304 time_spent = difftime(current_time, start_time); 305 306 rate = (double)(i / time_spent); 307 // printf("Generated %d addresses in %.1fs. Rate:%.1f/s \n", i, 308 // time_spent, rate); 309 } 310 311 i++; 312 } 313 314 /* Destroy context to free memory */ 315 secp256k1_context_destroy(ctx); 316 }