/* (C) folkert van heusden * released under AGPL v3.0 */ #include #include #include #include #include #include #include #include #include #define MODE_RANDOM 1 #define MODE_INCREMENTAL 2 #define MODE_FILE 3 #define MAX_PP_LEN 128 unsigned char passphrase[MAX_PP_LEN + 2]; unsigned char passphrase_template[MAX_PP_LEN + 2]; int min_length = 1; int max_length = MAX_PP_LEN; char *pp_file_in = NULL; FILE *pp_file_in_fh = NULL; long pp_file_in_offset = 0; /* this kludge is to make sure we have the file- * offset *before* the current passphrase as we * might get the signal while the current one * still is being processed */ char *pp_file_out = NULL; unsigned char charset[256]; int charset_n = 1; int mode = MODE_INCREMENTAL; /* int mode = MODE_RANDOM; */ long long int n_done = 0; void error_exit(char *str, gpgme_error_t err) { fprintf(stderr, "%s: %s\n", str, gpgme_strerror(err)); exit(1); } char valtohexdigit(int n) { if (n > 9) return 'A' + (n - 10); return '0' + n; } int hexdigittoval(char hex) { hex = toupper(hex); if (hex >= 'A') return hex - 'A' + 10; return hex - '0'; } int cvt_from_hex_string(char *in, char *out) { int loop, len = strlen(in), index = 0; for(loop=0; loop> 4), valtohexdigit(passphrase_template[loop] & 15)); fprintf(fh, "\n"); fprintf(fh, "charset="); for(loop=0; loop> 4), valtohexdigit(charset[loop] & 15)); fprintf(fh, "\n"); fprintf(fh, "min_length=%d\n", min_length); fprintf(fh, "max_length=%d\n", max_length); fprintf(fh, "n_done=%lld\n", n_done); if (mode == MODE_FILE) { fprintf(fh, "file=%s\n", pp_file_in); fprintf(fh, "file_offset=%ld\n", pp_file_in_offset); } fclose(fh); printf("\nState saved to 'nasty.state'\n"); exit(1); } } void not_found(void) { if (pp_file_out) { FILE *fh = fopen(pp_file_out, "w"); if (fh) { fprintf(fh, "passphrase_not_found\n"); fclose(fh); } else fprintf(stderr, "Failed to create file '%s': %s\n", pp_file_out, strerror(errno)); } else { printf("Passphrase not found.\n"); } exit(1); } /* Request a passphrase from the user. */ gpgme_error_t passphrase_cb(void *hook, const char *uid_hint, const char *passphrase_info, int prev_was_bad, int fd) { int loop, len = 0; if (mode == MODE_INCREMENTAL) { int index = 0; for(;;) { if (passphrase_template[index] < (charset_n - 1)) { passphrase_template[index]++; break; } else { passphrase_template[index] = 1; index++; if (index == max_length) not_found(); } } len = strlen((char *)passphrase_template); } else if (mode == MODE_RANDOM) { do { len = (rand() % (max_length - min_length)) + min_length; } while(len < min_length || len > max_length); for(loop=0; loop 1) { fprintf(stderr, "Cannot use commandline switches when using state-file from a previous run.\n"); fprintf(stderr, "Delete 'nasty.state' to start with other parameters.\n"); return 1; } goto skip_switches; } while((c = getopt(argc, argv, "a:b:m:c:f:i:k:h")) != -1) { switch(c) { case 'a': min_length = atoi(optarg); if (min_length < 1) { fprintf(stderr, "Min. passphrase length is 1\n"); return 1; } break; case 'b': max_length = atoi(optarg); if (max_length > MAX_PP_LEN) { fprintf(stderr, "Max. passphrase length is %d\n", MAX_PP_LEN); return 1; } break; case 'm': if (strcasecmp(optarg, "incremental") == 0) mode = MODE_INCREMENTAL; else if (strcasecmp(optarg, "random") == 0) mode = MODE_RANDOM; else if (strcasecmp(optarg, "file") == 0) mode = MODE_FILE; else { fprintf(stderr, "%s: unknown mode\n", optarg); return 1; } break; case 'c': for(loop=0; loop 2) { then = time(NULL); printf("# tried: %lld (%f per second), last tried: %s\r", n_done, n_done / (double)(then - start), passphrase); fflush(stdout); } } while(err != 0); gpgme_key_unref(selected_key); if (err == 0) printf("Passphrase is: %s\n", passphrase); else error_exit("gpgme_op_sign failed", err); if (pp_file_out) { FILE *fh = fopen(pp_file_out, "w"); if (fh) { fprintf(fh, "passphrase=%s\n", passphrase); fclose(fh); } else fprintf(stderr, "Failed to create file '%s': %s\n", pp_file_out, strerror(errno)); } (void)unlink("nasty.state"); return 0; }