/* $Id: bbs.c,v 1.2 2004/06/29 15:36:50 roo2b Exp $ */ /* *Copyright (c) 2004 Matthias Bauer * *Permission is hereby granted, free of charge, to any person obtaining a cop * *of this software and associated documentation files (the "Software"), to *deal in the Software without restriction, including without limitation the *rights to use, copy, modify, merge, publish, distribute, sublicense, *and/or sell copies of the Software, and to permit persons to whom the *Software is furnished to do so, subject to the following conditions: * *The above copyright notice and this permission notice shall be included in *all copies or substantial portions of the Software. * *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include /* Bessere Primtests */ /* Compile with * * gcc -I/usr/local/include -L/usr/local/lib -o bbs bbs.c -lcrypto -lgmp * * On Linux you must define -DDEVRAND="/dev/random" (untested) */ #define PRIMEFILE "blummod" #define SEEDFILE "bbsseed" #ifndef DEVRAND #define DEVRAND "/dev/arandom" #endif extern char *optarg; extern int optind; extern int optopt; extern int opterr; extern int optreset; FILE *conf, *seed; mpz_t i,j,n; mpz_t state, tmpstate; int foo, rfd, gflag,sflag, pflag, ch, intflag, statesize, nbytes; FILE *pfd, *sfd; char sfile[FILENAME_MAX] , pfile[FILENAME_MAX]; int bitsize = 512; int main(int argc, char** argv) { char *check; intflag = 0; while ((ch = getopt(argc, argv, "b:hgs:m:n:")) != -1) { switch(ch){ case 'g': gflag = 1; break; case 's': strlcpy(sfile, optarg, FILENAME_MAX ); sflag = 1; break; case 'm': strlcpy(pfile, optarg, FILENAME_MAX ); pflag = 1; break; case 'n': nbytes = strtol(optarg, &check, 10); if (optarg[0] == '\0' || *check != '\0') { fprintf(stderr, "Please give number of random bytes to the -n option\n"); exit(1); } break; case 'b': bitsize = atoi(optarg); break; case 'h': default: (void)usage(); } } if (!sflag) { strlcpy (sfile, SEEDFILE, 64); } if (!pflag) { strlcpy (pfile, PRIMEFILE, 64); } if (gflag) { char randini[128]; int i; if(( pfd = fopen (pfile, "w+")) == NULL) { fprintf(stderr, "Error opening %s\n", pfile); exit(1); } (void) gene_primes(pfd); fclose (pfd); if(( rfd = open (DEVRAND, O_RDONLY, 0)) < 0) { fprintf(stderr, "Could not open %s", DEVRAND); exit(1); } if (read(rfd, randini, 128) < 128) { fprintf(stderr, "Could not get 128 bytes from %s\n",DEVRAND); exit(1); } close (rfd); if(( sfd = fopen (sfile, "w+")) == NULL) { fprintf(stderr, "Error opening %s\n", sfile); exit(1); } for(i=0; i< 128; i++) { fprintf(sfd, "%.2x", randini[i]); } fprintf(sfd, "\n"); fclose (sfd); } if(!(conf = fopen (pfile, "r"))) { fprintf(stderr, "Could not open %s", pfile); exit(1); } if(!(seed = fopen (SEEDFILE, "r+"))) { fprintf(stderr, "Could not open SEEDFILE"); exit(1); } mpz_init(i); mpz_init(j); mpz_init(n); mpz_init(state); mpz_init(tmpstate); mpz_set_ui(n,0); mpz_inp_str(n, conf, 10); fclose (conf); if(mpz_cmp_ui(n,0) ==0) { fprintf(stderr, "Could not init modulus from %s\n", pfile); exit(1); } /* printf("Modulus: \n"); */ /* Mpz_out_str (stdout, 10, n); */ printf ("\n"); mpz_set_ui(state,0); mpz_inp_str(state,seed,16); if(mpz_cmp_ui(state,0) ==0) { fprintf(stderr, "Could not init state from %s\n", sfile); exit(1); } fclose (seed); while(nbytes > 0) { mpz_powm_ui (tmpstate, state, 2, n); foo = mpz_get_ui (tmpstate); fwrite(&foo, sizeof(int), 1, stdout); nbytes -= sizeof(int); mpz_set(state, tmpstate); statesize = mpz_sizeinbase (state, 16); fflush(stdout); } if ((seed = fopen(sfile, "w+")) == NULL) { fprintf(stderr, "Could not open %s for saving", sfile); _exit(1); } if(mpz_out_str(seed, 16, state) == statesize){ fprintf(stderr, "Wrote state to %s\n", sfile); fflush(seed); } else { fprintf(stderr, "Could not save state to %s\n", sfile); } _exit(1); } int gene_primes(FILE *fd) { BIGNUM *p, *q, *n; BN_CTX *cntx; cntx = BN_CTX_new(); BN_CTX_init(cntx); p = BN_new(); q = BN_new(); n = BN_new(); printf("\n\nI will now try to find two prime numbers p,q such that\n\t(p-1)/2 is prime _and_\n\t((p-1)/2-1)/2 is prime.\n\nThis will probably take a _long_ time (several hours on a Intel Pentium III at 466 Mhz)\n\n"); _gen_p (p, cntx); _gen_p (q, cntx); if (BN_mul(n, p, q, cntx) == 0) { fprintf(stderr, "Error in multiplication??\n"); exit(1); } fprintf (fd, "%s\n", BN_bn2dec(n)); return (1); } int usage (void) { fprintf(stdout,"Usage:\n\n\t-g\tgenerate primes and initial seed\n\t-s file\tname of seed file\n\t-m file\tname of modulus file\n\t-n num\tnumber of random bytes to return\n\t-b num\tbitsize of the prime numbers\n"); exit (0); } int _gen_p (BIGNUM *p, BN_CTX *cntx) { BIGNUM *q; q = BN_new(); printf ("Generating Germain^2 prime\n"); while (1) { BN_generate_prime(p, bitsize, 1, NULL, NULL, NULL, NULL); BN_rshift1(q,p); BN_rshift1(q,q); if (BN_is_prime_fasttest(q,20,NULL,cntx,NULL,1)) { printf( "Found one! The number is:\n%s\n", BN_bn2dec(p)); break; } fflush(stdout); } return; }