3 #include <d0_blind_id/d0_blind_id.h>
13 #include <sys/types.h>
16 // BEGIN stuff shared with crypto.c
17 #define FOURCC_D0PK (('d' << 0) | ('0' << 8) | ('p' << 16) | ('k' << 24))
18 #define FOURCC_D0SK (('d' << 0) | ('0' << 8) | ('s' << 16) | ('k' << 24))
19 #define FOURCC_D0PI (('d' << 0) | ('0' << 8) | ('p' << 16) | ('i' << 24))
20 #define FOURCC_D0SI (('d' << 0) | ('0' << 8) | ('s' << 16) | ('i' << 24))
21 #define FOURCC_D0IQ (('d' << 0) | ('0' << 8) | ('i' << 16) | ('q' << 24))
22 #define FOURCC_D0IR (('d' << 0) | ('0' << 8) | ('i' << 16) | ('r' << 24))
23 #define FOURCC_D0ER (('d' << 0) | ('0' << 8) | ('e' << 16) | ('r' << 24))
24 #define FOURCC_D0IC (('d' << 0) | ('0' << 8) | ('i' << 16) | ('c' << 24))
26 static unsigned long Crypto_LittleLong(const char *data)
29 ((unsigned char) data[0]) |
30 (((unsigned char) data[1]) << 8) |
31 (((unsigned char) data[2]) << 16) |
32 (((unsigned char) data[3]) << 24);
35 static void Crypto_UnLittleLong(char *data, unsigned long l)
38 data[1] = (l >> 8) & 0xFF;
39 data[2] = (l >> 16) & 0xFF;
40 data[3] = (l >> 24) & 0xFF;
43 static size_t Crypto_ParsePack(const char *buf, size_t len, unsigned long header, const char **lumps, size_t *lumpsize, size_t nlumps)
52 if(Crypto_LittleLong(buf) != header)
56 for(i = 0; i < nlumps; ++i)
60 lumpsize[i] = Crypto_LittleLong(&buf[pos]);
62 if(pos + lumpsize[i] > len)
70 static size_t Crypto_UnParsePack(char *buf, size_t len, unsigned long header, const char *const *lumps, const size_t *lumpsize, size_t nlumps)
79 Crypto_UnLittleLong(buf, header);
82 for(i = 0; i < nlumps; ++i)
84 if(pos + 4 + lumpsize[i] > len)
86 Crypto_UnLittleLong(&buf[pos], lumpsize[i]);
88 memcpy(&buf[pos], lumps[i], lumpsize[i]);
94 void file2buf(const char *fn, char **data, size_t *datasize)
100 if(!strncmp(f, "/dev/fd/", 8))
101 f = fdopen(atoi(fn + 8), "wb");
110 *data = realloc(*data, *datasize += 8192);
116 dn = fread(*data + n, 1, *datasize - n, f);
125 int buf2file(const char *fn, const char *data, size_t n)
128 if(!strncmp(f, "/dev/fd/", 8))
129 f = fdopen(atoi(fn + 8), "wb");
134 n = fwrite(data, n, 1, f);
140 void file2lumps(const char *fn, unsigned long header, const char **lumps, size_t *lumpsize, size_t nlumps)
144 file2buf(fn, &buf, &n);
147 fprintf(stderr, "could not open %s\n", fn);
150 if(!Crypto_ParsePack(buf, n, header, lumps, lumpsize, nlumps))
152 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);
160 void lumps2file(const char *fn, unsigned long header, const char *const *lumps, size_t *lumpsize, size_t nlumps, D0_BOOL private)
165 umask(umask_save | 0077);
168 if(!(n = Crypto_UnParsePack(buf, sizeof(buf), header, lumps, lumpsize, nlumps)))
170 fprintf(stderr, "could not unparse for %s\n", fn);
173 if(!buf2file(fn, buf, n))
175 fprintf(stderr, "could not write %s\n", fn);
180 void USAGE(const char *me)
183 "%s [-F] [-b bits] [-n progress-denominator] [-x prefix] [-X infix] [-C] -o private.d0sk\n"
184 "%s -P private.d0sk -o public.d0pk\n"
185 "%s [-n progress-denominator] [-x prefix] [-X infix] [-C] -p public.d0pk -o idkey-unsigned.d0si\n"
186 "%s -p public.d0pk -I idkey-unsigned.d0si -o request.d0iq -O camouflage.d0ic\n"
187 "%s -P private.d0sk -j request.d0iq -o response.d0ir\n"
188 "%s -p public.d0pk -I idkey-unsigned.d0si -c camouflage.d0ic -J response.d0ir -o idkey.d0si\n"
189 "%s -P private.d0sk -I idkey-unsigned.d0si -o idkey.d0si\n"
190 "%s -I idkey.d0si -o id.d0pi\n"
191 "%s -p public.d0pk\n"
192 "%s -P private.d0sk\n"
193 "%s -p public.d0pk -i id.d0pi\n"
194 "%s -p public.d0pk -I idkey.d0si\n"
195 "%s -0 -p public.d0pk -I idkey.d0si\n"
196 "%s -0 -p public.d0pk\n"
197 "%s -p public.d0pk -I idkey.d0si -d file-to-sign.dat -o file-signed.dat\n"
198 "%s -p public.d0pk -s file-signed.dat -o file-content.dat [-O id.d0pi]\n"
199 "%s -p public.d0pk -I idkey.d0si -d file-to-sign.dat -O signature.dat\n"
200 "%s -p public.d0pk -d file-to-sign.dat -s signature.dat [-O id.d0pi]\n",
201 me, me, me, me, me, me, me, me, me, me, me, me, me, me, me, me, me, me
205 unsigned int seconds;
206 unsigned int generated;
207 unsigned int ntasks = 1;
208 double generated_offset;
211 void print_generated(int signo)
215 if(generated >= 1000000000)
217 generated_offset += generated;
220 fprintf(stderr, "Generated: %.0f (about %.0f, %.1f/s, about %.2f hours for %.0f)\n",
221 // nasty and dishonest hack:
222 // we are adjusting the values "back", so the total count is
223 // divided by guessfactor (as the check function is called
224 // guessfactor as often as it would be if no fastreject were
226 // so the values indicate the relative speed of fastreject vs
228 (generated + generated_offset) / guessfactor,
229 (generated + generated_offset) * ntasks / guessfactor,
230 (generated + generated_offset) * ntasks / (guessfactor * seconds),
231 guesscount * ((guessfactor * seconds) / (generated + generated_offset) / ntasks) / 3600.0,
236 #define CHECK(x) if(!(x)) { fprintf(stderr, "error exit: error returned by %s\n", #x); exit(2); }
238 const char *prefix = NULL, *infix = NULL;
239 size_t prefixlen = 0;
241 typedef D0_BOOL (*fingerprint_func) (const d0_blind_id_t *ctx, char *outbuf, size_t *outbuflen);
242 D0_BOOL fastreject(const d0_blind_id_t *ctx, void *pass)
244 static char fp64[513]; size_t fp64size = 512;
245 CHECK(((fingerprint_func) pass)(ctx, fp64, &fp64size));
250 if(strncasecmp(fp64, prefix, prefixlen))
255 if(!strcasestr(fp64, infix))
262 if(memcmp(fp64, prefix, prefixlen))
267 if(!strstr(fp64, infix))
274 int main(int argc, char **argv)
278 const char *lumps[2];
279 char *databuf_in; size_t databufsize_in;
280 char *databuf_out; size_t databufsize_out;
281 char *databuf_sig; size_t databufsize_sig;
282 char lumps_w0[65536];
283 char lumps_w1[65536];
284 const char *pubkeyfile = NULL, *privkeyfile = NULL, *pubidfile = NULL, *prividfile = NULL, *idreqfile = NULL, *idresfile = NULL, *outfile = NULL, *outfile2 = NULL, *camouflagefile = NULL, *datafile = NULL, *sigfile = NULL;
285 char fp64[513]; size_t fp64size = 512;
289 D0_BOOL do_fastreject = 1;
291 if(!d0_blind_id_INITIALIZE())
293 fprintf(stderr, "could not initialize\n");
297 umask_save = umask(0022);
299 ctx = d0_blind_id_new();
300 while((opt = getopt(argc, argv, "d:s:p:P:i:I:j:J:o:O:c:b:x:X:y:Fn:C0")) != -1)
308 ntasks = atoi(optarg);
313 case 'p': // d0pk = <pubkey> <modulus>
317 case 'P': // d0sk = <privkey> <modulus>
318 privkeyfile = optarg;
321 case 'i': // d0pi = <pubid>
325 case 'I': // d0si = <privid>
329 case 'j': // d0iq = <req>
333 case 'J': // d0ir = <resp>
346 camouflagefile = optarg;
351 prefixlen = strlen(prefix);
377 // fastreject is a slight slowdown when rejecting nothing at all
378 if(!infix && !prefixlen)
381 guesscount = pow(64.0, prefixlen);
383 guesscount /= (1 - pow(1 - pow(1/64.0, strlen(infix)), 44 - prefixlen - strlen(infix)));
384 // 44 chars; prefix is assumed to not match the infix (although it theoretically could)
385 // 43'th char however is always '=' and does not count
389 for(i = 0; infix[i]; ++i)
390 if(toupper(infix[i]) != tolower(infix[i]))
392 for(i = 0; i < (int)prefixlen; ++i)
393 if(toupper(prefix[i]) != tolower(prefix[i]))
399 // fastreject: reject function gets called about log(2^bits) times more often
400 guessfactor = bits * log(2) / 2;
401 // so guess function gets called guesscount * guessfactor times, and it tests as many valid keys as guesscount
406 file2lumps(pubkeyfile, FOURCC_D0PK, lumps, lumpsize, 2);
407 if(!d0_blind_id_read_public_key(ctx, lumps[0], lumpsize[0]))
409 fprintf(stderr, "could not decode public key\n");
412 if(!d0_blind_id_read_private_id_modulus(ctx, lumps[1], lumpsize[1]))
414 fprintf(stderr, "could not decode modulus\n");
420 file2lumps(privkeyfile, FOURCC_D0SK, lumps, lumpsize, 2);
421 if(!d0_blind_id_read_private_key(ctx, lumps[0], lumpsize[0]))
423 fprintf(stderr, "could not decode private key\n");
426 if(!d0_blind_id_read_private_id_modulus(ctx, lumps[1], lumpsize[1]))
428 fprintf(stderr, "could not decode modulus\n");
435 file2lumps(pubidfile, FOURCC_D0PI, lumps, lumpsize, 1);
436 if(!d0_blind_id_read_public_id(ctx, lumps[0], lumpsize[0]))
438 fprintf(stderr, "could not decode public ID\n");
444 file2lumps(prividfile, FOURCC_D0SI, lumps, lumpsize, 1);
445 if(!d0_blind_id_read_private_id(ctx, lumps[0], lumpsize[0]))
447 fprintf(stderr, "could not decode private ID\n");
454 file2lumps(idreqfile, FOURCC_D0IQ, lumps, lumpsize, 1);
455 lumpsize[1] = sizeof(lumps_w1);
457 if(!d0_blind_id_answer_private_id_request(ctx, lumps[0], lumpsize[0], lumps_w1, &lumpsize[1]))
459 fprintf(stderr, "could not answer private ID request\n");
463 else if((mask & 0x120) == 0x120)
465 file2lumps(camouflagefile, FOURCC_D0IC, lumps, lumpsize, 1);
466 if(!d0_blind_id_read_private_id_request_camouflage(ctx, lumps[0], lumpsize[0]))
468 fprintf(stderr, "could not decode camouflage\n");
472 file2lumps(idresfile, FOURCC_D0IR, lumps, lumpsize, 1);
473 if(!d0_blind_id_finish_private_id_request(ctx, lumps[0], lumpsize[0]))
475 fprintf(stderr, "could not finish private ID request\n");
482 file2buf(datafile, &databuf_in, &databufsize_in);
485 fprintf(stderr, "could not decode data\n");
492 file2buf(sigfile, &databuf_sig, &databufsize_sig);
495 fprintf(stderr, "could not decode signature\n");
502 // modes of operation:
504 // nothing -> private key file (incl modulus), print fingerprint
506 generated_offset = 0;
508 signal(SIGALRM, print_generated);
512 CHECK(d0_blind_id_generate_private_key_fastreject(ctx, bits, fastreject, d0_blind_id_fingerprint64_public_key));
516 guessfactor = 1; // no fastreject here
519 CHECK(d0_blind_id_generate_private_key(ctx, bits));
521 while(fastreject(ctx, d0_blind_id_fingerprint64_public_key));
524 signal(SIGALRM, NULL);
525 CHECK(d0_blind_id_generate_private_id_modulus(ctx));
527 lumpsize[0] = sizeof(lumps_w0);
529 lumpsize[1] = sizeof(lumps_w1);
530 CHECK(d0_blind_id_write_private_key(ctx, lumps_w0, &lumpsize[0]));
531 CHECK(d0_blind_id_write_private_id_modulus(ctx, lumps_w1, &lumpsize[1]));
532 lumps2file(outfile, FOURCC_D0SK, lumps, lumpsize, 2, 1);
535 // private key file -> public key file (incl modulus)
537 lumpsize[0] = sizeof(lumps_w0);
539 lumpsize[1] = sizeof(lumps_w1);
540 CHECK(d0_blind_id_write_public_key(ctx, lumps_w0, &lumpsize[0]));
541 CHECK(d0_blind_id_write_private_id_modulus(ctx, lumps_w1, &lumpsize[1]));
542 lumps2file(outfile, FOURCC_D0PK, lumps, lumpsize, 2, 0);
545 // public key file -> unsigned private ID file
547 generated_offset = 0;
549 signal(SIGALRM, print_generated);
551 guessfactor = 1; // no fastreject here
554 CHECK(d0_blind_id_generate_private_id_start(ctx));
556 while(fastreject(ctx, d0_blind_id_fingerprint64_public_id));
560 lumpsize[0] = sizeof(lumps_w0);
561 CHECK(d0_blind_id_write_private_id(ctx, lumps_w0, &lumpsize[0]));
562 lumps2file(outfile, FOURCC_D0SI, lumps, lumpsize, 1, 1);
565 // public key file, unsigned private ID file -> ID request file and camouflage file
567 lumpsize[0] = sizeof(lumps_w0);
568 CHECK(d0_blind_id_generate_private_id_request(ctx, lumps_w0, &lumpsize[0]));
569 lumps2file(outfile, FOURCC_D0IQ, lumps, lumpsize, 1, 0);
570 lumpsize[0] = sizeof(lumps_w0);
571 CHECK(d0_blind_id_write_private_id_request_camouflage(ctx, lumps_w0, &lumpsize[0]));
572 lumps2file(outfile2, FOURCC_D0IC, lumps, lumpsize, 1, 1);
575 // private key file, ID request file -> ID response file
576 lumps2file(outfile, FOURCC_D0IR, lumps+1, lumpsize+1, 1, 0);
579 // public key file, ID response file, private ID file -> signed private ID file
581 lumpsize[0] = sizeof(lumps_w0);
582 CHECK(d0_blind_id_write_private_id(ctx, lumps_w0, &lumpsize[0]));
583 lumps2file(outfile, FOURCC_D0SI, lumps, lumpsize, 1, 1);
586 // private key file, private ID file -> signed private ID file
588 char buf[65536]; size_t bufsize;
589 char buf2[65536]; size_t buf2size;
591 d0_blind_id_t *ctx2 = d0_blind_id_new();
592 CHECK(d0_blind_id_copy(ctx2, ctx));
593 bufsize = sizeof(buf);
594 CHECK(d0_blind_id_authenticate_with_private_id_start(ctx, 1, 1, "hello world", 11, buf, &bufsize));
595 buf2size = sizeof(buf2);
596 CHECK(d0_blind_id_authenticate_with_private_id_challenge(ctx2, 1, 1, buf, bufsize, buf2, &buf2size, &status));
597 bufsize = sizeof(buf);
598 CHECK(d0_blind_id_authenticate_with_private_id_response(ctx, buf2, buf2size, buf, &bufsize));
599 buf2size = sizeof(buf2);
600 CHECK(d0_blind_id_authenticate_with_private_id_verify(ctx2, buf, bufsize, buf2, &buf2size, &status));
602 CHECK(d0_blind_id_authenticate_with_private_id_generate_missing_signature(ctx2));
604 lumpsize[0] = sizeof(lumps_w0);
605 CHECK(d0_blind_id_write_private_id(ctx2, lumps_w0, &lumpsize[0]));
606 lumps2file(outfile, FOURCC_D0SI, lumps, lumpsize, 1, 1);
610 // private ID file -> public ID file
612 lumpsize[0] = sizeof(lumps_w0);
613 CHECK(d0_blind_id_write_public_id(ctx, lumps_w0, &lumpsize[0]));
614 lumps2file(outfile, FOURCC_D0PI, lumps, lumpsize, 1, 0);
618 // public/private key file -> fingerprint
619 CHECK(d0_blind_id_fingerprint64_public_key(ctx, fp64, &fp64size));
620 printf("%.*s\n", (int)fp64size, fp64);
624 // public/private ID file -> fingerprint
625 CHECK(d0_blind_id_fingerprint64_public_id(ctx, fp64, &fp64size));
626 printf("%.*s\n", (int)fp64size, fp64);
629 // public key, private ID, data -> signed data
630 databufsize_out = databufsize_in + 8192;
631 databuf_out = malloc(databufsize_out);
632 CHECK(d0_blind_id_sign_with_private_id_sign(ctx, 1, 0, databuf_in, databufsize_in, databuf_out, &databufsize_out));
633 buf2file(outfile, databuf_out, databufsize_out);
636 // public key, private ID, data -> signature
637 databufsize_out = databufsize_in + 8192;
638 databuf_out = malloc(databufsize_out);
639 CHECK(d0_blind_id_sign_with_private_id_sign_detached(ctx, 1, 0, databuf_in, databufsize_in, databuf_out, &databufsize_out));
640 buf2file(outfile2, databuf_out, databufsize_out);
644 // public key, signed data -> data, optional public ID
647 databufsize_out = databufsize_sig;
648 databuf_out = malloc(databufsize_out);
649 CHECK(d0_blind_id_sign_with_private_id_verify(ctx, 1, 0, databuf_sig, databufsize_sig, databuf_out, &databufsize_out, &status));
650 CHECK(d0_blind_id_fingerprint64_public_id(ctx, fp64, &fp64size));
651 printf("%d\n", (int)status);
652 printf("%.*s\n", (int)fp64size, fp64);
653 buf2file(outfile, databuf_out, databufsize_out);
658 lumpsize[0] = sizeof(lumps_w0);
660 lumpsize[1] = sizeof(lumps_w1);
661 CHECK(d0_blind_id_write_public_key(ctx, lumps_w0, &lumpsize[0]));
662 CHECK(d0_blind_id_write_private_id_modulus(ctx, lumps_w1, &lumpsize[1]));
663 lumps2file(outfile2, FOURCC_D0PK, lumps, lumpsize, 2, 0);
669 // public key, signature, signed data -> optional public ID
672 CHECK(d0_blind_id_sign_with_private_id_verify_detached(ctx, 1, 0, databuf_sig, databufsize_sig, databuf_in, databufsize_in, &status));
673 CHECK(d0_blind_id_fingerprint64_public_id(ctx, fp64, &fp64size));
674 printf("%d\n", (int)status);
675 printf("%.*s\n", (int)fp64size, fp64);
676 buf2file(outfile, databuf_out, databufsize_out);
681 lumpsize[0] = sizeof(lumps_w0);
683 lumpsize[1] = sizeof(lumps_w1);
684 CHECK(d0_blind_id_write_public_key(ctx, lumps_w0, &lumpsize[0]));
685 CHECK(d0_blind_id_write_private_id_modulus(ctx, lumps_w1, &lumpsize[1]));
686 lumps2file(outfile2, FOURCC_D0PK, lumps, lumpsize, 2, 0);
692 // public key, private ID file -> test whether key is properly signed
694 char buf[65536]; size_t bufsize;
695 char buf2[65536]; size_t buf2size;
697 d0_blind_id_t *ctx2 = d0_blind_id_new();
698 CHECK(d0_blind_id_copy(ctx2, ctx));
699 bufsize = sizeof(buf);
700 CHECK(d0_blind_id_authenticate_with_private_id_start(ctx, 1, 1, "hello world", 11, buf, &bufsize));
701 buf2size = sizeof(buf2);
702 CHECK(d0_blind_id_authenticate_with_private_id_challenge(ctx2, 1, 1, buf, bufsize, buf2, &buf2size, &status));
703 bufsize = sizeof(buf);
704 CHECK(d0_blind_id_authenticate_with_private_id_response(ctx, buf2, buf2size, buf, &bufsize));
705 buf2size = sizeof(buf2);
706 CHECK(d0_blind_id_authenticate_with_private_id_verify(ctx2, buf, bufsize, buf2, &buf2size, &status));
710 printf("EPIC FAIL\n");
718 const char hex[] = "0123456789abcdef";
719 char buf[65536]; size_t bufsize;
720 char buf2[65536]; size_t buf2size;
721 bufsize = sizeof(buf);
722 CHECK(d0_blind_id_authenticate_with_private_id_start(ctx, 1, 1, "hello world", 11, buf, &bufsize));
723 for(i = 0; i < (int)bufsize; ++i)
724 sprintf(&hexbuf[2*i], "%02x", (unsigned char)buf[i]);
725 printf("%s\n", hexbuf);
726 fgets(hexbuf, sizeof(hexbuf), stdin);
727 buf2size = strlen(hexbuf) / 2;
728 for(i = 0; i < (int)buf2size; ++i)
729 buf2[i] = ((strchr(hex, hexbuf[2*i]) - hex) << 4) | (strchr(hex, hexbuf[2*i+1]) - hex);
730 bufsize = sizeof(buf);
731 CHECK(d0_blind_id_authenticate_with_private_id_response(ctx, buf2, buf2size, buf, &bufsize));
732 for(i = 0; i < (int)bufsize; ++i)
733 sprintf(&hexbuf[2*i], "%02x", (unsigned char)buf[i]);
734 printf("%s\n", hexbuf);
741 const char hex[] = "0123456789abcdef";
742 char buf[65536]; size_t bufsize;
743 char buf2[65536]; size_t buf2size;
745 fgets(hexbuf, sizeof(hexbuf), stdin);
746 buf2size = strlen(hexbuf) / 2;
747 for(i = 0; i < (int)buf2size; ++i)
748 buf2[i] = ((strchr(hex, hexbuf[2*i]) - hex) << 4) | (strchr(hex, hexbuf[2*i+1]) - hex);
749 bufsize = sizeof(buf);
750 CHECK(d0_blind_id_authenticate_with_private_id_challenge(ctx, 1, 1, buf2, buf2size, buf, &bufsize, &status));
751 for(i = 0; i < (int)bufsize; ++i)
752 sprintf(&hexbuf[2*i], "%02x", (unsigned char)buf[i]);
753 printf("%s\n", hexbuf);
754 fgets(hexbuf, sizeof(hexbuf), stdin);
755 buf2size = strlen(hexbuf) / 2;
756 for(i = 0; i < (int)buf2size; ++i)
757 buf2[i] = ((strchr(hex, hexbuf[2*i]) - hex) << 4) | (strchr(hex, hexbuf[2*i+1]) - hex);
758 bufsize = sizeof(buf);
759 CHECK(d0_blind_id_authenticate_with_private_id_verify(ctx, buf2, buf2size, buf, &bufsize, &status));
760 printf("verify status: %d\n", status);
762 CHECK(d0_blind_id_fingerprint64_public_id(ctx, fp64, &fp64size));
763 printf("%.*s\n", (int)fp64size, fp64);
771 d0_blind_id_SHUTDOWN();