1 #include <d0_blind_id/d0_blind_id.h>
10 #include <sys/types.h>
13 // BEGIN stuff shared with crypto.c
14 #define FOURCC_D0PK (('d' << 0) | ('0' << 8) | ('p' << 16) | ('k' << 24))
15 #define FOURCC_D0SK (('d' << 0) | ('0' << 8) | ('s' << 16) | ('k' << 24))
16 #define FOURCC_D0PI (('d' << 0) | ('0' << 8) | ('p' << 16) | ('i' << 24))
17 #define FOURCC_D0SI (('d' << 0) | ('0' << 8) | ('s' << 16) | ('i' << 24))
18 #define FOURCC_D0IQ (('d' << 0) | ('0' << 8) | ('i' << 16) | ('q' << 24))
19 #define FOURCC_D0IR (('d' << 0) | ('0' << 8) | ('i' << 16) | ('r' << 24))
20 #define FOURCC_D0ER (('d' << 0) | ('0' << 8) | ('e' << 16) | ('r' << 24))
21 #define FOURCC_D0IC (('d' << 0) | ('0' << 8) | ('i' << 16) | ('c' << 24))
23 static unsigned long Crypto_LittleLong(const char *data)
26 ((unsigned char) data[0]) |
27 (((unsigned char) data[1]) << 8) |
28 (((unsigned char) data[2]) << 16) |
29 (((unsigned char) data[3]) << 24);
32 static void Crypto_UnLittleLong(char *data, unsigned long l)
35 data[1] = (l >> 8) & 0xFF;
36 data[2] = (l >> 16) & 0xFF;
37 data[3] = (l >> 24) & 0xFF;
40 static size_t Crypto_ParsePack(const char *buf, size_t len, unsigned long header, const char **lumps, size_t *lumpsize, size_t nlumps)
49 if(Crypto_LittleLong(buf) != header)
53 for(i = 0; i < nlumps; ++i)
57 lumpsize[i] = Crypto_LittleLong(&buf[pos]);
59 if(pos + lumpsize[i] > len)
67 static size_t Crypto_UnParsePack(char *buf, size_t len, unsigned long header, const char *const *lumps, const size_t *lumpsize, size_t nlumps)
76 Crypto_UnLittleLong(buf, header);
79 for(i = 0; i < nlumps; ++i)
81 if(pos + 4 + lumpsize[i] > len)
83 Crypto_UnLittleLong(&buf[pos], lumpsize[i]);
85 memcpy(&buf[pos], lumps[i], lumpsize[i]);
91 void file2lumps(const char *fn, unsigned long header, const char **lumps, size_t *lumpsize, size_t nlumps)
99 fprintf(stderr, "could not open %s\n", fn);
102 n = fread(buf, 1, sizeof(buf), f);
104 if(!Crypto_ParsePack(buf, n, header, lumps, lumpsize, nlumps))
106 fprintf(stderr, "could not parse %s as %c%c%c%c (%d lumps expected)\n", fn, (int) header & 0xFF, (int) (header >> 8) & 0xFF, (int) (header >> 16) & 0xFF, (int) (header >> 24) & 0xFF, (int) nlumps);
112 void lumps2file(const char *fn, unsigned long header, const char *const *lumps, size_t *lumpsize, size_t nlumps, D0_BOOL private)
118 umask(umask_save | 0077);
124 fprintf(stderr, "could not open %s\n", fn);
127 if(!(n = Crypto_UnParsePack(buf, sizeof(buf), header, lumps, lumpsize, nlumps)))
129 fprintf(stderr, "could not unparse for %s\n", fn);
132 n = fwrite(buf, n, 1, f);
135 fprintf(stderr, "could not write %s\n", fn);
140 void USAGE(const char *me)
143 "%s [-F] [-b bits] [-n progress-denominator] [-x prefix] [-X infix] [-C] -o private.d0sk\n"
144 "%s -P private.d0sk -o public.d0pk\n"
145 "%s [-n progress-denominator] [-x prefix] [-X infix] [-C] -p public.d0pk -o idkey-unsigned.d0si\n"
146 "%s -p public.d0pk -I idkey-unsigned.d0si -o request.d0iq -O camouflage.d0ic\n"
147 "%s -P private.d0sk -j request.d0iq -o response.d0ir\n"
148 "%s -p public.d0pk -I idkey-unsigned.d0si -c camouflage.d0ic -J response.d0ir -o idkey.d0si\n"
149 "%s -P private.d0sk -I idkey-unsigned.d0si -o idkey.d0si\n"
150 "%s -I idkey.d0si -o id.d0pi\n"
151 "%s -p public.d0pk\n"
152 "%s -P private.d0sk\n"
153 "%s -p public.d0pk -i id.d0pi\n"
154 "%s -p public.d0pk -I idkey.d0si\n",
155 me, me, me, me, me, me, me, me, me, me, me, me
159 unsigned int seconds;
160 unsigned int generated;
161 unsigned int ntasks = 1;
162 double generated_offset;
165 void print_generated(int signo)
169 if(generated >= 1000000000)
171 generated_offset += generated;
174 fprintf(stderr, "Generated: %.0f (about %.0f, %.1f/s, about %.2f hours for %.0f)\n",
175 // nasty and dishonest hack:
176 // we are adjusting the values "back", so the total count is
177 // divided by guessfactor (as the check function is called
178 // guessfactor as often as it would be if no fastreject were
180 // so the values indicate the relative speed of fastreject vs
182 (generated + generated_offset) / guessfactor,
183 (generated + generated_offset) * ntasks / guessfactor,
184 (generated + generated_offset) * ntasks / (guessfactor * seconds),
185 guesscount * ((guessfactor * seconds) / (generated + generated_offset) / ntasks) / 3600.0,
190 #define CHECK(x) if(!(x)) { fprintf(stderr, "error exit: error returned by %s\n", #x); exit(2); }
192 const char *prefix = NULL, *infix = NULL;
193 size_t prefixlen = 0;
195 typedef D0_BOOL (*fingerprint_func) (const d0_blind_id_t *ctx, char *outbuf, size_t *outbuflen);
196 D0_BOOL fastreject(const d0_blind_id_t *ctx, void *pass)
198 static char fp64[513]; size_t fp64size = 512;
199 CHECK(((fingerprint_func) pass)(ctx, fp64, &fp64size));
204 if(strncasecmp(fp64, prefix, prefixlen))
209 if(!strcasestr(fp64, infix))
216 if(memcmp(fp64, prefix, prefixlen))
221 if(!strstr(fp64, infix))
228 int main(int argc, char **argv)
232 const char *lumps[2];
233 char lumps_w0[65536];
234 char lumps_w1[65536];
235 const char *pubkeyfile = NULL, *privkeyfile = NULL, *pubidfile = NULL, *prividfile = NULL, *idreqfile = NULL, *idresfile = NULL, *outfile = NULL, *outfile2 = NULL, *camouflagefile = NULL;
236 char fp64[513]; size_t fp64size = 512;
240 D0_BOOL do_fastreject = 1;
242 if(!d0_blind_id_INITIALIZE())
244 fprintf(stderr, "could not initialize\n");
248 umask_save = umask(0022);
250 ctx = d0_blind_id_new();
251 while((opt = getopt(argc, argv, "p:P:i:I:j:J:o:O:c:b:x:X:y:Fn:C")) != -1)
259 ntasks = atoi(optarg);
264 case 'p': // d0pk = <pubkey> <modulus>
268 case 'P': // d0sk = <privkey> <modulus>
269 privkeyfile = optarg;
272 case 'i': // d0pi = <pubid>
276 case 'I': // d0si = <privid>
280 case 'j': // d0iq = <req>
284 case 'J': // d0ir = <resp>
297 camouflagefile = optarg;
302 prefixlen = strlen(prefix);
316 // fastreject is a slight slowdown when rejecting nothing at all
317 if(!infix && !prefixlen)
320 guesscount = pow(64.0, prefixlen);
322 guesscount /= (1 - pow(1 - pow(1/64.0, strlen(infix)), 44 - prefixlen - strlen(infix)));
323 // 44 chars; prefix is assumed to not match the infix (although it theoretically could)
324 // 43'th char however is always '=' and does not count
328 for(i = 0; infix[i]; ++i)
329 if(toupper(infix[i]) != tolower(infix[i]))
331 for(i = 0; i < prefixlen; ++i)
332 if(toupper(prefix[i]) != tolower(prefix[i]))
338 // fastreject: reject function gets called about log(2^bits) times more often
339 guessfactor = bits * log(2) / 2;
340 // so guess function gets called guesscount * guessfactor times, and it tests as many valid keys as guesscount
345 file2lumps(pubkeyfile, FOURCC_D0PK, lumps, lumpsize, 2);
346 if(!d0_blind_id_read_public_key(ctx, lumps[0], lumpsize[0]))
348 fprintf(stderr, "could not decode public key\n");
351 if(!d0_blind_id_read_private_id_modulus(ctx, lumps[1], lumpsize[1]))
353 fprintf(stderr, "could not decode modulus\n");
359 file2lumps(privkeyfile, FOURCC_D0SK, lumps, lumpsize, 2);
360 if(!d0_blind_id_read_private_key(ctx, lumps[0], lumpsize[0]))
362 fprintf(stderr, "could not decode private key\n");
365 if(!d0_blind_id_read_private_id_modulus(ctx, lumps[1], lumpsize[1]))
367 fprintf(stderr, "could not decode modulus\n");
374 file2lumps(pubidfile, FOURCC_D0PI, lumps, lumpsize, 1);
375 if(!d0_blind_id_read_public_id(ctx, lumps[0], lumpsize[0]))
377 fprintf(stderr, "could not decode public ID\n");
383 file2lumps(prividfile, FOURCC_D0SI, lumps, lumpsize, 1);
384 if(!d0_blind_id_read_private_id(ctx, lumps[0], lumpsize[0]))
386 fprintf(stderr, "could not decode private ID\n");
393 file2lumps(idreqfile, FOURCC_D0IQ, lumps, lumpsize, 1);
394 lumpsize[1] = sizeof(lumps_w1);
396 if(!d0_blind_id_answer_private_id_request(ctx, lumps[0], lumpsize[0], lumps_w1, &lumpsize[1]))
398 fprintf(stderr, "could not answer private ID request\n");
402 else if((mask & 0x120) == 0x120)
404 file2lumps(camouflagefile, FOURCC_D0IC, lumps, lumpsize, 1);
405 if(!d0_blind_id_read_private_id_request_camouflage(ctx, lumps[0], lumpsize[0]))
407 fprintf(stderr, "could not decode camouflage\n");
411 file2lumps(idresfile, FOURCC_D0IR, lumps, lumpsize, 1);
412 if(!d0_blind_id_finish_private_id_request(ctx, lumps[0], lumpsize[0]))
414 fprintf(stderr, "could not finish private ID request\n");
421 // modes of operation:
423 // nothing -> private key file (incl modulus), print fingerprint
425 generated_offset = 0;
427 signal(SIGALRM, print_generated);
431 CHECK(d0_blind_id_generate_private_key_fastreject(ctx, bits, fastreject, d0_blind_id_fingerprint64_public_key));
435 guessfactor = 1; // no fastreject here
438 CHECK(d0_blind_id_generate_private_key(ctx, bits));
440 while(fastreject(ctx, d0_blind_id_fingerprint64_public_key));
443 signal(SIGALRM, NULL);
444 CHECK(d0_blind_id_generate_private_id_modulus(ctx));
446 lumpsize[0] = sizeof(lumps_w0);
448 lumpsize[1] = sizeof(lumps_w1);
449 CHECK(d0_blind_id_write_private_key(ctx, lumps_w0, &lumpsize[0]));
450 CHECK(d0_blind_id_write_private_id_modulus(ctx, lumps_w1, &lumpsize[1]));
451 lumps2file(outfile, FOURCC_D0SK, lumps, lumpsize, 2, 1);
454 // private key file -> public key file (incl modulus)
456 lumpsize[0] = sizeof(lumps_w0);
458 lumpsize[1] = sizeof(lumps_w1);
459 CHECK(d0_blind_id_write_public_key(ctx, lumps_w0, &lumpsize[0]));
460 CHECK(d0_blind_id_write_private_id_modulus(ctx, lumps_w1, &lumpsize[1]));
461 lumps2file(outfile, FOURCC_D0PK, lumps, lumpsize, 2, 0);
464 // public key file -> unsigned private ID file
466 generated_offset = 0;
468 signal(SIGALRM, print_generated);
470 guessfactor = 1; // no fastreject here
473 CHECK(d0_blind_id_generate_private_id_start(ctx));
475 while(fastreject(ctx, d0_blind_id_fingerprint64_public_id));
479 lumpsize[0] = sizeof(lumps_w0);
480 CHECK(d0_blind_id_write_private_id(ctx, lumps_w0, &lumpsize[0]));
481 lumps2file(outfile, FOURCC_D0SI, lumps, lumpsize, 1, 1);
484 // public key file, unsigned private ID file -> ID request file and camouflage file
486 lumpsize[0] = sizeof(lumps_w0);
487 CHECK(d0_blind_id_generate_private_id_request(ctx, lumps_w0, &lumpsize[0]));
488 lumps2file(outfile, FOURCC_D0IQ, lumps, lumpsize, 1, 0);
489 lumpsize[0] = sizeof(lumps_w0);
490 CHECK(d0_blind_id_write_private_id_request_camouflage(ctx, lumps_w0, &lumpsize[0]));
491 lumps2file(outfile2, FOURCC_D0IC, lumps, lumpsize, 1, 1);
494 // private key file, ID request file -> ID response file
495 lumps2file(outfile, FOURCC_D0IR, lumps+1, lumpsize+1, 1, 0);
498 // public key file, ID response file, private ID file -> signed private ID file
500 lumpsize[0] = sizeof(lumps_w0);
501 CHECK(d0_blind_id_write_private_id(ctx, lumps_w0, &lumpsize[0]));
502 lumps2file(outfile, FOURCC_D0SI, lumps, lumpsize, 1, 1);
505 // private key file, private ID file -> signed private ID file
507 char buf[65536]; size_t bufsize;
508 char buf2[65536]; size_t buf2size;
510 d0_blind_id_t *ctx2 = d0_blind_id_new();
511 CHECK(d0_blind_id_copy(ctx2, ctx));
512 bufsize = sizeof(buf);
513 CHECK(d0_blind_id_authenticate_with_private_id_start(ctx, 1, 1, "hello world", 11, buf, &bufsize));
514 buf2size = sizeof(buf2);
515 CHECK(d0_blind_id_authenticate_with_private_id_challenge(ctx2, 1, 1, buf, bufsize, buf2, &buf2size, &status));
516 bufsize = sizeof(buf);
517 CHECK(d0_blind_id_authenticate_with_private_id_response(ctx, buf2, buf2size, buf, &bufsize));
518 buf2size = sizeof(buf2);
519 CHECK(d0_blind_id_authenticate_with_private_id_verify(ctx2, buf, bufsize, buf2, &buf2size, &status));
521 CHECK(d0_blind_id_authenticate_with_private_id_generate_missing_signature(ctx2));
523 lumpsize[0] = sizeof(lumps_w0);
524 CHECK(d0_blind_id_write_private_id(ctx2, lumps_w0, &lumpsize[0]));
525 lumps2file(outfile, FOURCC_D0SI, lumps, lumpsize, 1, 1);
529 // private ID file -> public ID file
531 lumpsize[0] = sizeof(lumps_w0);
532 CHECK(d0_blind_id_write_public_id(ctx, lumps_w0, &lumpsize[0]));
533 lumps2file(outfile, FOURCC_D0PI, lumps, lumpsize, 1, 0);
537 // public/private key file -> fingerprint
538 CHECK(d0_blind_id_fingerprint64_public_key(ctx, fp64, &fp64size));
539 printf("%.*s\n", (int)fp64size, fp64);
543 // public/private ID file -> fingerprint
544 CHECK(d0_blind_id_fingerprint64_public_id(ctx, fp64, &fp64size));
545 printf("%.*s\n", (int)fp64size, fp64);
549 // public key, private ID file -> test whether key is properly signed
551 char buf[65536]; size_t bufsize;
552 char buf2[65536]; size_t buf2size;
554 d0_blind_id_t *ctx2 = d0_blind_id_new();
555 CHECK(d0_blind_id_copy(ctx2, ctx));
556 bufsize = sizeof(buf);
557 CHECK(d0_blind_id_authenticate_with_private_id_start(ctx, 1, 1, "hello world", 11, buf, &bufsize));
558 buf2size = sizeof(buf2);
559 CHECK(d0_blind_id_authenticate_with_private_id_challenge(ctx2, 1, 1, buf, bufsize, buf2, &buf2size, &status));
560 bufsize = sizeof(buf);
561 CHECK(d0_blind_id_authenticate_with_private_id_response(ctx, buf2, buf2size, buf, &bufsize));
562 buf2size = sizeof(buf2);
563 CHECK(d0_blind_id_authenticate_with_private_id_verify(ctx2, buf, bufsize, buf2, &buf2size, &status));
567 printf("EPIC FAIL\n");
576 d0_blind_id_SHUTDOWN();