RSA *RSA_generate_key(int bits, unsigned long e_value, void (*callback)(int,int,void *), void *cb_arg) { RSA *rsa=NULL; BIGNUM *r0=NULL,*r1=NULL,*r2=NULL,*r3=NULL,*tmp; int bitsp,bitsq,ok= -1,n=0,i; BN_CTX *ctx=NULL,*ctx2=NULL; ctx=BN_CTX_new(); if (ctx == NULL) goto err; ctx2=BN_CTX_new(); if (ctx2 == NULL) goto err; BN_CTX_start(ctx); r0 = BN_CTX_get(ctx); r1 = BN_CTX_get(ctx); r2 = BN_CTX_get(ctx); r3 = BN_CTX_get(ctx); if (r3 == NULL) goto err; bitsp=(bits+1)/2; bitsq=bits-bitsp; rsa=RSA_new(); if (rsa == NULL) goto err; /* set e */ rsa->e=BN_new(); if (rsa->e == NULL) goto err; /* The problem is when building with 8, 16, or 32 BN_ULONG, * unsigned long can be larger */ for (i=0; i<sizeof(unsigned long)*8; i++) { if (e_value & (1UL<<i)) BN_set_bit(rsa->e,i); } /* generate p and q */ for (;;) { rsa->p=BN_generate_prime(NULL,bitsp,0,NULL,NULL,callback,cb_arg); if (rsa->p == NULL) goto err; if (!BN_sub(r2,rsa->p,BN_value_one())) goto err; if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err; if (BN_is_one(r1)) break; if (callback != NULL) callback(2,n++,cb_arg); BN_free(rsa->p); } if (callback != NULL) callback(3,0,cb_arg); for (;;) { rsa->q=BN_generate_prime(NULL,bitsq,0,NULL,NULL,callback,cb_arg); if (rsa->q == NULL) goto err; if (!BN_sub(r2,rsa->q,BN_value_one())) goto err; if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err; if (BN_is_one(r1) && (BN_cmp(rsa->p,rsa->q) != 0)) break; if (callback != NULL) callback(2,n++,cb_arg); BN_free(rsa->q); } if (callback != NULL) callback(3,1,cb_arg); if (BN_cmp(rsa->p,rsa->q) < 0) { tmp=rsa->p; rsa->p=rsa->q; rsa->q=tmp; } /* calculate n */ rsa->n=BN_new(); if (rsa->n == NULL) goto err; if (!BN_mul(rsa->n,rsa->p,rsa->q,ctx)) goto err; /* calculate d */ if (!BN_sub(r1,rsa->p,BN_value_one())) goto err; /* p-1 */ if (!BN_sub(r2,rsa->q,BN_value_one())) goto err; /* q-1 */ if (!BN_mul(r0,r1,r2,ctx)) goto err; /* (p-1)(q-1) */ /* should not be needed, since gcd(p-1,e) == 1 and gcd(q-1,e) == 1 */ /* for (;;) { if (!BN_gcd(r3,r0,rsa->e,ctx)) goto err; if (BN_is_one(r3)) break; if (1) { if (!BN_add_word(rsa->e,2L)) goto err; continue; } RSAerr(RSA_F_RSA_GENERATE_KEY,RSA_R_BAD_E_VALUE); goto err; } */ rsa->d=BN_mod_inverse(NULL,rsa->e,r0,ctx2); /* d */ if (rsa->d == NULL) goto err; /* calculate d mod (p-1) */ rsa->dmp1=BN_new(); if (rsa->dmp1 == NULL) goto err; if (!BN_mod(rsa->dmp1,rsa->d,r1,ctx)) goto err; /* calculate d mod (q-1) */ rsa->dmq1=BN_new(); if (rsa->dmq1 == NULL) goto err; if (!BN_mod(rsa->dmq1,rsa->d,r2,ctx)) goto err; /* calculate inverse of q mod p */ rsa->iqmp=BN_mod_inverse(NULL,rsa->q,rsa->p,ctx2); if (rsa->iqmp == NULL) goto err; ok=1; err: if (ok == -1) ok=0; BN_CTX_end(ctx); BN_CTX_free(ctx); BN_CTX_free(ctx2); if (!ok) { if (rsa != NULL) RSA_free(rsa); return(NULL); } else return(rsa); }
/* * call-seq: * BN.generate_prime(bits, [, safe [, add [, rem]]]) => bn * * === Parameters * * +bits+ - integer * * +safe+ - boolean * * +add+ - BN * * +rem+ - BN */ static VALUE ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass) { BIGNUM *add = NULL, *rem = NULL, *result; int safe = 1, num; VALUE vnum, vsafe, vadd, vrem, obj; rb_scan_args(argc, argv, "13", &vnum, &vsafe, &vadd, &vrem); num = NUM2INT(vnum); if (vsafe == Qfalse) { safe = 0; } if (!NIL_P(vadd)) { add = GetBNPtr(vadd); rem = NIL_P(vrem) ? NULL : GetBNPtr(vrem); } if (!(result = BN_new())) { ossl_raise(eBNError, NULL); } if (!BN_generate_prime(result, num, safe, add, rem, NULL, NULL)) { BN_free(result); ossl_raise(eBNError, NULL); } WrapBN(klass, obj, result); return obj; }
/** * Generate a prime number * * The internal CPRNG is seeded using the provided seed value. * * @param prime Pointer for storage of prime number * @param s Secret to share * @param bits Bit size of prime * @param rngSeed Seed value for CPRNG * @param rngSeedLength Length of Seed value for CPRNG * */ static int generatePrime(BIGNUM *prime, const BIGNUM *s, const int bits, unsigned char *rngSeed, const unsigned int rngSeedLength) { int max_rounds = 1000; // Seed the RNG RAND_seed(rngSeed, rngSeedLength); // Clear the prime value BN_clear(prime); do { // Generate random prime #if OPENSSL_VERSION_NUMBER >= 0x00908000L /* last parm is BN_GENCB which is null in our case */ BN_generate_prime_ex(prime, bits, 1, NULL, NULL, NULL); #else BN_generate_prime(prime, bits, 1, NULL, NULL, NULL, NULL ); #endif } while ((BN_ucmp(prime, s) == -1) && (max_rounds-- > 0)); // If prime < s or not reached 1000 tries if (max_rounds > 0) return 0; else return -1; // We could not find a prime number }
void test_lehmer_thm(void) { BIGNUM *v = BN_new(), *v2 = BN_new(), *h = BN_new(), *n = BN_new(), *p = BN_new(), *q = BN_new(), *g = BN_new(); BN_CTX *ctx = BN_CTX_new(); BN_dec2bn(&v, "2"); BN_dec2bn(&p, "181857351165158586099319592412492032999818333818932850952491024" "131283899677766672100915923041329384157985577418702469610834914" "6296393743554494871840505599"); BN_dec2bn(&q, "220481921324130321200060036818685031159071785249502660004347524" "831733577485433929892260897846567483448177204481081755191897197" "38283711758138566145322943999"); BN_mul(n, p, q, ctx); /* p + 1 */ BN_dec2bn(&h, "181857351165158586099319592412492032999818333818932850952491024" "131283899677766672100915923041329384157985577418702469610834914" "6296393743554494871840505600"); lucas(v, h, n, ctx); BN_sub(v2, v, BN_value_two()); BN_gcd(g, v2, n, ctx); assert(!BN_is_one(g)); /* another test */ BN_dec2bn(&v, "3"); BN_dec2bn(&p, "181857351165158586099319592412492032999818333818932850952491024" "131283899677766672100915923041329384157985577418702469610834914" "62963937435544948718405055999"); BN_generate_prime(q, 512, 1, NULL, NULL, NULL, NULL); BN_mul(n, p, q, ctx); BN_sub(h, p, BN_value_one()); BN_mul(h, h, BN_value_two(), ctx); lucas(v, h, n, ctx); BN_mod_sub(v2, v, BN_value_two(), n, ctx); BN_gcd(g, v2, n, ctx); assert(!BN_is_one(g)); assert(BN_cmp(g, n)); BN_free(q); BN_free(p); BN_free(v); BN_free(v2); BN_free(h); BN_CTX_free(ctx); }
void DS::GenPrimeKeys(uint8_t* K, uint8_t* N) { BIGNUM* bn_key = BN_new(); init_rand(); while (BN_num_bytes(bn_key) != 64) { BN_generate_prime(bn_key, 512, 1, 0, 0, 0, 0); putc('.', stdout); fflush(stdout); } BN_bn2bin(bn_key, reinterpret_cast<unsigned char*>(K)); BN_set_word(bn_key, 0); while (BN_num_bytes(bn_key) != 64) { BN_generate_prime(bn_key, 512, 1, 0, 0, 0, 0); putc('.', stdout); fflush(stdout); } BN_bn2bin(bn_key, reinterpret_cast<unsigned char*>(N)); BN_free(bn_key); }
/** * Generate a prime number * * The internal CPRNG is seeded using the provided seed value. * For the bit size of the generated prime the following condition holds: * * num_bits(prime) > max(2^r, num_bits(n + 1)) * * r equals the number of bits needed to encode the secret. * * @param prime Pointer for storage of prime number * @param s Secret to share * @param n Maximum number of shares * @param rngSeed Seed value for CPRNG * */ static void generatePrime(BIGNUM *prime, const BIGNUM *s, const unsigned int n, char *rngSeed) { int bits = 0; // Seed the RNG RAND_seed(rngSeed, sizeof(rngSeed)); // Determine minimum number of bits for prime >= max(2^r, n + 1) bits = BN_num_bits_word(n + 1) > BN_num_bits(s) ? (BN_num_bits_word(n + 1)) : (BN_num_bits(s)); // Clear the prime value BN_clear(prime); // Generate random prime BN_generate_prime(prime, bits, 1, NULL, NULL, NULL, NULL ); }
int main(int argc, char *argv[]) { char *prime; BIGNUM *num_tmp; long int num_bits = 0; if(argc >= 2 && argv[1]) num_bits = atol(argv[1]); else num_bits = 1024; printf("Prime generator by (c) 2004 Paolo Ardoino < *****@*****.** >\n usage: ./genprimes [num_bits]\nGenerating %ld bits primes.\nWait…\n",num_bits); num_tmp = BN_new(); for (;;) { BN_generate_prime(num_tmp,num_bits,1,NULL,NULL,status,NULL); prime = (char *)malloc(BN_num_bytes(num_tmp)); prime = BN_bn2dec(num_tmp); print_prime(prime); free(prime); } BN_free(num_tmp); }
/* generates ElGamal key pair. returns 0 when generation went ok, and -1 if error occured. 'bits' is the number of bits in p; it should not be too low (at least 512 is recommended, 1024 is more realistic number. you can use precomputed p,g pairs; set bits to the ordinal of the precomputed combination (see table above). generator is either 2 or 5. public_key and secret_key will be malloc()ed and contain keys */ int eg_keypair (int bits, int generator, char **public_key, char **secret_key) { BIGNUM *p, *g, *t1, *t2, *key, *pbk; BN_CTX *ctx2; BN_MONT_CTX *mont; char *buf1, *buf2, *buf3, *buf4, buf[8]; int rc; // create things needed for work ctx2 = BN_CTX_new (); if (ctx2 == NULL) return -1; t1 = BN_new (); if (t1 == NULL) return -1; t2 = BN_new (); if (t2 == NULL) return -1; g = BN_new (); if (g == NULL) return -1; key = BN_new (); if (key == NULL) return -1; pbk = BN_new (); if (pbk == NULL) return -1; mont = BN_MONT_CTX_new (); if (mont == NULL) return -1; if (bits < 32) { if (bits > sizeof(precomp)/sizeof(precomp[0])-1) return -1; p = NULL; rc = BN_hex2bn (&p, precomp[bits].prime); if (rc == 0) return -1; // put generator into bignum BN_set_word (g, precomp[bits].generator); } else { // set values which will be used for checking when generating proper prime if (generator == 2) { BN_set_word (t1,24); BN_set_word (t2,11); } else if (generator == 5) { BN_set_word (t1,10); BN_set_word (t2,3); /* BN_set_word(t3,7); just have to miss * out on these ones :-( */ } else goto err; // generate proper prime p = BN_generate_prime (NULL, bits, 1, t1, t2, NULL, NULL); if (p == NULL) goto err; // put generator into bignum BN_set_word (g, generator); } // create random private key if (!BN_rand (key, BN_num_bits (p)-1, 0, 0)) goto err; // create public part of the key BN_MONT_CTX_set (mont, p, ctx2); if (!BN_mod_exp_mont (pbk, g, key, p, ctx2, mont)) goto err; // p, g, key, pbk are ready. secret key: p,g:key, public key: p,g:pbk if (bits < 32) { snprintf1 (buf, sizeof(buf), "%d", bits); buf1 = strdup (buf); } else { buf1 = BN_bn2hex (p); } buf2 = BN_bn2hex (key); buf3 = BN_bn2hex (pbk); buf4 = BN_bn2hex (g); *secret_key = malloc (strlen(buf1) + strlen(buf2) + strlen(buf4) + 4); *public_key = malloc (strlen(buf1) + strlen(buf3) + strlen(buf4) + 4); strcpy (*secret_key, buf1); if (bits >= 32) { strcat (*secret_key, ","); strcat (*secret_key, buf4); } strcat (*secret_key, ":"); strcat (*secret_key, buf2); strcpy (*public_key, buf1); if (bits >= 32) { strcat (*public_key, ","); strcat (*public_key, buf4); } strcat (*public_key, ":"); strcat (*public_key, buf3); memset (buf2, 0, strlen (buf2)); free (buf1); free (buf2); free (buf3); // cleanup BN_free (p); BN_free (g); BN_clear_free (key); BN_free (pbk); BN_CTX_free (ctx2); return 0; err: return -1; }
int main() { clock_t begin, end; double time_spent; printf("====================================================================\n"); BIGNUM *a, *b, *c, *d, *gen, *prime_mod; char *c_str; BN_CTX *ctx; /* used internally by the bignum lib */ //DH *dhparms; int csize; ctx = BN_CTX_new(); a = BN_new(); b = BN_new(); c = BN_new(); d = BN_new(); prime_mod = BN_new(); BN_set_word(a, 6); BN_set_word(b, 7); BN_mul(c, a, b, ctx); BN_generate_prime(prime_mod,1024,0,0,0,0,0); //char * primeMOD= "D3BAAE3CE4015583027B1D822109B874CDC6A805BEFEB3DA4B6AD9C3DC1D90B1CF04D70906A1897AF231A03041D6456E7113C573E038DE0EDCF7CAE1B237AC2328110681C83AE86CC5E3268B5808551575E066858684448336E32A9BBCDDAA248BC2685C94142E88C6A68B021941B1C60744E137122A20A7D2CB1641B01E0117"; //BN_hex2bn(&prime_mod, primeMOD); c_str = BN_bn2hex(prime_mod); /* there's also a BN_d ec2bn() */ csize = BN_num_bits(prime_mod); //printf("prime_mod = %s size = %d\n", c_str, csize); // BN_rand(c, 1024, 0, 0); // c_str = BN_bn2hex(c); //there's also a BN_d ec2bn() // csize = BN_num_bits(c); // printf("C = %s size = %d\n", c_str, csize); //char * BN_T= "DFB9E8DC1BA16AD6EB2ABE6C02E5A9C7B279EEB52DEEBFD550172FC59CAF08534DFEC64BDDE9BD1BE6F9FBDA376C917E615C1F639FE81B8A594812D3E64B3AE4D7BB3F735106845571E16C348CB5100B71B805B70D0CF293727FEAF48F3FFD2A88B09D14AD9D6E314E35BB72238DFAD2549FCF7554F3E1645B118AADACCA35FA"; // BN_hex2bn(&d, BN_T); // c_str = BN_bn2hex(d); // csize = BN_num_bits(d); // printf("D = %s size = %d\n", c_str, csize); // BN_sqr(c, d, ctx); // c = d^2 // c_str = BN_bn2hex(c); // csize = BN_num_bits(c); // printf("c sq = %s size = %d\n", c_str, csize); // BN_mod_add(b, b, c, prime_mod, ctx); //b = b+c mod p // BN_mod(d, c, prime_mod, ctx); // d = c mod p // c_str = BN_bn2hex(d); // csize = BN_num_bits(d); // printf("c mod d = %s size = %d\n", c_str, csize); // BN_mod_exp(b, c, d, prime_mod, ctx); // b = c^d mod p // c_str = BN_bn2hex(b); // csize = BN_num_bits(b); // printf("c exp d = %s size = %d\n", c_str, csize); int i, j, _ITERATION_NOR, _ITERATION_EXP; _ITERATION_NOR = 1000000; _ITERATION_EXP = 1000; time_t now; time(&now); struct tm* now_tm; now_tm = localtime(&now); char out[80]; char fileNameT[80]; strftime (out, 80, "%Y-%m-%d %H:%M:%S", now_tm); strftime (fileNameT, 80, "%Y.%m.%d.%H.%M.%S", now_tm); char filename[20]; strcpy (filename,"Bignumber_"); strcat (filename,fileNameT); strcat (filename,".txt"); FILE *f = fopen(filename, "a+"); //setbuf(f, NULL); if (f == NULL) { printf("Error opening file!\n"); exit(1); } fprintf(f, "\nTested started on %s\n", out); fprintf(f, "Normal iteration = %d\n", _ITERATION_NOR); fprintf(f, "Exp iteration = %d\n", _ITERATION_EXP); fprintf(f, "MOD iteration = %d\n", _ITERATION_NOR*10); fprintf(f, "===================================\n"); for(j=0;j<100;j++){ printf("Iteration\t#%d\n", j+1); fprintf(f, "Iteration #%d\n", j+1); fflush(f); BN_rand(a, 1024, 0, 0); BN_rand(d, 1024, 0, 0); // d^2 begin = clock(); for(i=0;i<_ITERATION_NOR;i++){ BN_sqr(c, d, ctx); } end = clock(); time_spent = (double)(end - begin) / CLOCKS_PER_SEC; printf("Square %f\n", time_spent); fprintf(f, "Square\t%f\n", time_spent); fflush(f); BN_rand(b, 1024, 0, 0); BN_rand(c, 1024, 0, 0); // b+c begin = clock(); for(i=0;i<_ITERATION_NOR;i++){ BN_mod_add(b, b, c, prime_mod, ctx); } end = clock(); time_spent = (double)(end - begin) / CLOCKS_PER_SEC; printf("Addition %f\n", time_spent); fprintf(f, "Addition\t%f\n", time_spent); fflush(f); BN_rand(b, 1024, 0, 0); // b mod p begin = clock(); for(i=0;i<_ITERATION_NOR*10;i++){ BN_mod(d, b, prime_mod, ctx); } end = clock(); time_spent = (double)(end - begin) / CLOCKS_PER_SEC; printf("Modulus %f\n", time_spent); fprintf(f, "Modulus\t%f\n", time_spent); fflush(f); BN_rand(c, 1024, 0, 0); BN_rand(d, 1024, 0, 0); // c ^ d mod p begin = clock(); for(i=0;i<_ITERATION_EXP;i++){ BN_mod_exp(b, c, d, prime_mod, ctx); // b = c^d mod p } end = clock(); time_spent = (double)(end - begin) / CLOCKS_PER_SEC; printf("exponetial %f\n", time_spent); fprintf(f, "exponetial\t%f\n", time_spent); fflush(f); } time(&now); now_tm = localtime(&now); strftime (out, 80, "%Y-%m-%d %H:%M:%S", now_tm); fprintf(f, "\nTested ended on %s\n", out); BN_CTX_free(ctx); printf("====================================================================\n"); fclose(f); return 0; }
int test_sqrt(BIO *bp, BN_CTX *ctx) { BIGNUM *a,*p,*r; int i, j; int ret = 0; a = BN_new(); p = BN_new(); r = BN_new(); if (a == NULL || p == NULL || r == NULL) goto err; for (i = 0; i < 16; i++) { if (i < 8) { unsigned primes[8] = { 2, 3, 5, 7, 11, 13, 17, 19 }; if (!BN_set_word(p, primes[i])) goto err; } else { if (!BN_set_word(a, 32)) goto err; if (!BN_set_word(r, 2*i + 1)) goto err; if (!BN_generate_prime(p, 256, 0, a, r, genprime_cb, NULL)) goto err; putc('\n', stderr); } p->neg = rand_neg(); for (j = 0; j < num2; j++) { /* construct 'a' such that it is a square modulo p, * but in general not a proper square and not reduced modulo p */ if (!BN_bntest_rand(r, 256, 0, 3)) goto err; if (!BN_nnmod(r, r, p, ctx)) goto err; if (!BN_mod_sqr(r, r, p, ctx)) goto err; if (!BN_bntest_rand(a, 256, 0, 3)) goto err; if (!BN_nnmod(a, a, p, ctx)) goto err; if (!BN_mod_sqr(a, a, p, ctx)) goto err; if (!BN_mul(a, a, r, ctx)) goto err; if (rand_neg()) if (!BN_sub(a, a, p)) goto err; if (!BN_mod_sqrt(r, a, p, ctx)) goto err; if (!BN_mod_sqr(r, r, p, ctx)) goto err; if (!BN_nnmod(a, a, p, ctx)) goto err; if (BN_cmp(a, r) != 0) { fprintf(stderr, "BN_mod_sqrt failed: a = "); BN_print_fp(stderr, a); fprintf(stderr, ", r = "); BN_print_fp(stderr, r); fprintf(stderr, ", p = "); BN_print_fp(stderr, p); fprintf(stderr, "\n"); goto err; } putc('.', stderr); fflush(stderr); } putc('\n', stderr); fflush(stderr); } ret = 1; err: if (a != NULL) BN_free(a); if (p != NULL) BN_free(p); if (r != NULL) BN_free(r); return ret; }
int test_kron(BIO *bp, BN_CTX *ctx) { BIGNUM *a,*b,*r,*t; int i; int legendre, kronecker; int ret = 0; a = BN_new(); b = BN_new(); r = BN_new(); t = BN_new(); if (a == NULL || b == NULL || r == NULL || t == NULL) goto err; /* We test BN_kronecker(a, b, ctx) just for b odd (Jacobi symbol). * In this case we know that if b is prime, then BN_kronecker(a, b, ctx) * is congruent to $a^{(b-1)/2}$, modulo $b$ (Legendre symbol). * So we generate a random prime b and compare these values * for a number of random a's. (That is, we run the Solovay-Strassen * primality test to confirm that b is prime, except that we * don't want to test whether b is prime but whether BN_kronecker * works.) */ if (!BN_generate_prime(b, 512, 0, NULL, NULL, genprime_cb, NULL)) goto err; b->neg = rand_neg(); putc('\n', stderr); for (i = 0; i < num0; i++) { if (!BN_bntest_rand(a, 512, 0, 0)) goto err; a->neg = rand_neg(); /* t := (|b|-1)/2 (note that b is odd) */ if (!BN_copy(t, b)) goto err; t->neg = 0; if (!BN_sub_word(t, 1)) goto err; if (!BN_rshift1(t, t)) goto err; /* r := a^t mod b */ b->neg=0; if (!BN_mod_exp_recp(r, a, t, b, ctx)) goto err; b->neg=1; if (BN_is_word(r, 1)) legendre = 1; else if (BN_is_zero(r)) legendre = 0; else { if (!BN_add_word(r, 1)) goto err; if (0 != BN_ucmp(r, b)) { fprintf(stderr, "Legendre symbol computation failed\n"); goto err; } legendre = -1; } kronecker = BN_kronecker(a, b, ctx); if (kronecker < -1) goto err; /* we actually need BN_kronecker(a, |b|) */ if (a->neg && b->neg) kronecker = -kronecker; if (legendre != kronecker) { fprintf(stderr, "legendre != kronecker; a = "); BN_print_fp(stderr, a); fprintf(stderr, ", b = "); BN_print_fp(stderr, b); fprintf(stderr, "\n"); goto err; } putc('.', stderr); fflush(stderr); } putc('\n', stderr); fflush(stderr); ret = 1; err: if (a != NULL) BN_free(a); if (b != NULL) BN_free(b); if (r != NULL) BN_free(r); if (t != NULL) BN_free(t); return ret; }
DH *DH_generate_parameters(int prime_len, int generator, void (*callback)(int,int,void *), void *cb_arg) { BIGNUM *p=NULL,*t1,*t2; DH *ret=NULL; int g,ok= -1; BN_CTX *ctx=NULL; ret=DH_new(); if (ret == NULL) goto err; ctx=BN_CTX_new(); if (ctx == NULL) goto err; BN_CTX_start(ctx); t1 = BN_CTX_get(ctx); t2 = BN_CTX_get(ctx); if (t1 == NULL || t2 == NULL) goto err; if (generator == DH_GENERATOR_2) { BN_set_word(t1,24); BN_set_word(t2,11); g=2; } #ifdef undef /* does not work for safe primes */ else if (generator == DH_GENERATOR_3) { BN_set_word(t1,12); BN_set_word(t2,5); g=3; } #endif else if (generator == DH_GENERATOR_5) { BN_set_word(t1,10); BN_set_word(t2,3); /* BN_set_word(t3,7); just have to miss * out on these ones :-( */ g=5; } else g=generator; p=BN_generate_prime(NULL,prime_len,1,t1,t2,callback,cb_arg); if (p == NULL) goto err; if (callback != NULL) callback(3,0,cb_arg); ret->p=p; ret->g=BN_new(); if (!BN_set_word(ret->g,g)) goto err; ok=1; err: if (ok == -1) { DHerr(DH_F_DH_GENERATE_PARAMETERS,ERR_R_BN_LIB); ok=0; } if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (!ok && (ret != NULL)) { DH_free(ret); ret=NULL; } return(ret); }
int rsa_keypair (int bits, unsigned long e_value, char **public_key, char **secret_key) { BIGNUM *n=NULL, *e=NULL, *d=NULL, *p=NULL, *q=NULL; BIGNUM *r0=NULL, *r1=NULL, *r2=NULL, *r3=NULL, *tmp; int bitsp, bitsq, i; BN_CTX *ctx=NULL, *ctx2=NULL; char *buf1, *buf2, *buf3; ctx=BN_CTX_new(); if (ctx == NULL) goto err; ctx2=BN_CTX_new(); if (ctx2 == NULL) goto err; r0 = &(ctx->bn[0]); r1 = &(ctx->bn[1]); r2 = &(ctx->bn[2]); r3 = &(ctx->bn[3]); ctx->tos += 4; bitsp = (bits+1)/2; bitsq = bits-bitsp; /* set e */ e = BN_new(); if (e == NULL) goto err; /* The problem is when building with 8, 16, or 32 BN_ULONG, * unsigned long can be larger */ for (i=0; i<sizeof(unsigned long)*8; i++) { if (e_value & (1<<i)) BN_set_bit(e,i); } /* generate p and q */ for (;;) { p = BN_generate_prime (NULL, bitsp, 1, NULL, NULL, NULL, NULL); if (p == NULL) goto err; if (!BN_sub (r2, p, BN_value_one())) goto err; if (!BN_gcd (r1, r2, e, ctx)) goto err; if (BN_is_one(r1)) break; BN_free(p); } for (;;) { q = BN_generate_prime (NULL, bitsq, 1, NULL, NULL, NULL, NULL); if (q == NULL) goto err; if (!BN_sub (r2, q, BN_value_one())) goto err; if (!BN_gcd (r1, r2, e, ctx)) goto err; if (BN_is_one (r1) && (BN_cmp (p, q) != 0)) break; BN_free(q); } if (BN_cmp (p, q) < 0) tmp = p, p = q, q = tmp; /* calculate n */ n = BN_new(); if (n == NULL) goto err; if (!BN_mul (n, p, q, ctx)) goto err; /* calculate d */ if (!BN_sub (r1, p, BN_value_one())) goto err; /* p-1 */ if (!BN_sub (r2, q, BN_value_one())) goto err; /* q-1 */ if (!BN_mul (r0, r1, r2, ctx)) goto err; /* (p-1)(q-1) */ d = BN_mod_inverse (NULL, e, r0, ctx2); /* d */ if (d == NULL) goto err; BN_CTX_free(ctx); BN_CTX_free(ctx2); // n, d, e are ready. secret key: n:d, public key: n:e buf1 = BN_bn2hex (n); buf2 = BN_bn2hex (d); buf3 = BN_bn2hex (e); *secret_key = malloc (strlen(buf1) + strlen(buf2) + 2); *public_key = malloc (strlen(buf1) + strlen(buf3) + 2); strcpy (*secret_key, buf1); strcat (*secret_key, ":"); strcat (*secret_key, buf2); strcpy (*public_key, buf1); strcat (*public_key, ":"); strcat (*public_key, buf3); free (buf1); free (buf2); free (buf3); // cleanup BN_clear_free (n); BN_clear_free (e); BN_clear_free (d); BN_clear_free (p); BN_clear_free (q); return 0; err: BN_CTX_free(ctx); BN_CTX_free(ctx2); return -1; }
/* Actually there is no reason to insist that 'generator' be a generator. * It's just as OK (and in some sense better) to use a generator of the * order-q subgroup. */ DH *DH_generate_parameters(int prime_len, int generator, void (*callback)(int,int,void *), void *cb_arg) { BIGNUM *p=NULL,*t1,*t2; DH *ret=NULL; int g,ok= -1; BN_CTX *ctx=NULL; ret=DH_new(); if (ret == NULL) goto err; ctx=BN_CTX_new(); if (ctx == NULL) goto err; BN_CTX_start(ctx); t1 = BN_CTX_get(ctx); t2 = BN_CTX_get(ctx); if (t1 == NULL || t2 == NULL) goto err; if (generator <= 1) { DHerr(DH_F_DH_GENERATE_PARAMETERS, DH_R_BAD_GENERATOR); goto err; } if (generator == DH_GENERATOR_2) { if (!BN_set_word(t1,24)) goto err; if (!BN_set_word(t2,11)) goto err; g=2; } #if 0 /* does not work for safe primes */ else if (generator == DH_GENERATOR_3) { if (!BN_set_word(t1,12)) goto err; if (!BN_set_word(t2,5)) goto err; g=3; } #endif else if (generator == DH_GENERATOR_5) { if (!BN_set_word(t1,10)) goto err; if (!BN_set_word(t2,3)) goto err; /* BN_set_word(t3,7); just have to miss * out on these ones :-( */ g=5; } else { /* in the general case, don't worry if 'generator' is a * generator or not: since we are using safe primes, * it will generate either an order-q or an order-2q group, * which both is OK */ if (!BN_set_word(t1,2)) goto err; if (!BN_set_word(t2,1)) goto err; g=generator; } p=BN_generate_prime(NULL,prime_len,1,t1,t2,callback,cb_arg); if (p == NULL) goto err; if (callback != NULL) callback(3,0,cb_arg); ret->p=p; ret->g=BN_new(); if (!BN_set_word(ret->g,g)) goto err; ok=1; err: if (ok == -1) { DHerr(DH_F_DH_GENERATE_PARAMETERS,ERR_R_BN_LIB); ok=0; } if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (!ok && (ret != NULL)) { DH_free(ret); ret=NULL; } return(ret); }
void do_mul_exp(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx) { int i,k; double tm; long num; num=BASENUM; for (i=NUM_START; i<NUM_SIZES; i++) { #ifdef C_PRIME # ifdef TEST_SQRT if (!BN_set_word(a, 64)) goto err; if (!BN_set_word(b, P_MOD_64)) goto err; # define ADD a # define REM b # else # define ADD NULL # define REM NULL # endif if (!BN_generate_prime(c,sizes[i],0,ADD,REM,genprime_cb,NULL)) goto err; putc('\n', stderr); fflush(stderr); #endif for (k=0; k<num; k++) { if (k%50 == 0) /* Average over num/50 different choices of random numbers. */ { if (!BN_pseudo_rand(a,sizes[i],1,0)) goto err; if (!BN_pseudo_rand(b,sizes[i],1,0)) goto err; #ifndef C_PRIME if (!BN_pseudo_rand(c,sizes[i],1,1)) goto err; #endif #ifdef TEST_SQRT if (!BN_mod_sqr(a,a,c,ctx)) goto err; if (!BN_mod_sqr(b,b,c,ctx)) goto err; #else if (!BN_nnmod(a,a,c,ctx)) goto err; if (!BN_nnmod(b,b,c,ctx)) goto err; #endif if (k == 0) Time_F(START); } #if defined(TEST_EXP) if (!BN_mod_exp(r,a,b,c,ctx)) goto err; #elif defined(TEST_MUL) { int i = 0; for (i = 0; i < 50; i++) if (!BN_mod_mul(r,a,b,c,ctx)) goto err; } #elif defined(TEST_SQR) { int i = 0; for (i = 0; i < 50; i++) { if (!BN_mod_sqr(r,a,c,ctx)) goto err; if (!BN_mod_sqr(r,b,c,ctx)) goto err; } } #elif defined(TEST_GCD) if (!BN_gcd(r,a,b,ctx)) goto err; if (!BN_gcd(r,b,c,ctx)) goto err; if (!BN_gcd(r,c,a,ctx)) goto err; #elif defined(TEST_KRON) if (-2 == BN_kronecker(a,b,ctx)) goto err; if (-2 == BN_kronecker(b,c,ctx)) goto err; if (-2 == BN_kronecker(c,a,ctx)) goto err; #elif defined(TEST_INV) if (!BN_mod_inverse(r,a,c,ctx)) goto err; if (!BN_mod_inverse(r,b,c,ctx)) goto err; #else /* TEST_SQRT */ if (!BN_mod_sqrt(r,a,c,ctx)) goto err; if (!BN_mod_sqrt(r,b,c,ctx)) goto err; #endif } tm=Time_F(STOP); printf( #if defined(TEST_EXP) "modexp %4d ^ %4d %% %4d" #elif defined(TEST_MUL) "50*modmul %4d %4d %4d" #elif defined(TEST_SQR) "100*modsqr %4d %4d %4d" #elif defined(TEST_GCD) "3*gcd %4d %4d %4d" #elif defined(TEST_KRON) "3*kronecker %4d %4d %4d" #elif defined(TEST_INV) "2*inv %4d %4d mod %4d" #else /* TEST_SQRT */ "2*sqrt [prime == %d (mod 64)] %4d %4d mod %4d" #endif " -> %8.3fms %5.1f (%ld)\n", #ifdef TEST_SQRT P_MOD_64, #endif sizes[i],sizes[i],sizes[i],tm*1000.0/num,tm*mul_c[i]/num, num); num/=7; if (num <= 0) num=1; } return; err: ERR_print_errors_fp(stderr); }