/* * pr_fact - print the factors of a number * * Print the factors of the number, from the lowest to the highest. * A factor will be printed multiple times if it divides the value * multiple times. * * Factors are printed with leading tabs. */ static void pr_fact(BIGNUM *val) { const ubig *fact; /* The factor found. */ /* Firewall - catch 0 and 1. */ if (BN_is_zero(val)) /* Historical practice; 0 just exits. */ exit(0); if (BN_is_one(val)) { printf("1: 1\n"); return; } /* Factor value. */ if (hflag) { fputs("0x", stdout); BN_print_fp(stdout, val); } else BN_print_dec_fp(stdout, val); putchar(':'); for (fact = &prime[0]; !BN_is_one(val); ++fact) { /* Look for the smallest factor. */ do { if (BN_mod_word(val, (BN_ULONG)*fact) == 0) break; } while (++fact <= pr_limit); /* Watch for primes larger than the table. */ if (fact > pr_limit) { #ifdef HAVE_OPENSSL BIGNUM *bnfact; bnfact = BN_new(); BN_set_word(bnfact, *(fact - 1)); if (!BN_sqr(bnfact, bnfact, ctx)) errx(1, "error in BN_sqr()"); if (BN_cmp(bnfact, val) > 0 || BN_is_prime(val, PRIME_CHECKS, NULL, NULL, NULL) == 1) pr_print(val); else pollard_pminus1(val); #else pr_print(val); #endif break; } /* Divide factor out until none are left. */ do { printf(hflag ? " 0x%lx" : " %lu", *fact); BN_div_word(val, (BN_ULONG)*fact); } while (BN_mod_word(val, (BN_ULONG)*fact) == 0); /* Let the user know we're doing something. */ fflush(stdout); } putchar('\n'); }
/* slow but works */ int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx) { BIGNUM *t; int ret = 0; bn_check_top(a); bn_check_top(b); bn_check_top(m); BN_CTX_start(ctx); if ((t = BN_CTX_get(ctx)) == NULL) goto err; if (a == b) { if (!BN_sqr(t, a, ctx)) goto err; } else { if (!BN_mul(t, a,b, ctx)) goto err; } if (!BN_nnmod(r, t,m, ctx)) goto err; bn_check_top(r); ret = 1; err: BN_CTX_end(ctx); return (ret); }
int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) { if (!BN_sqr(r, a, ctx)) return 0; /* r->neg == 0, thus we don't need BN_nnmod */ return BN_mod(r, r, m, ctx); }
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_MONT_CTX *mont, BN_CTX *ctx) { BIGNUM *tmp; int ret=0; BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); if (tmp == NULL) goto err; bn_check_top(tmp); if (a == b) { if (!BN_sqr(tmp,a,ctx)) goto err; } else { if (!BN_mul(tmp,a,b,ctx)) goto err; } /* reduce from aRR to aR */ if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err; bn_check_top(r); ret=1; err: BN_CTX_end(ctx); return(ret); }
int ec_GFp_nist_field_sqr(const EC_GROUP * group, BIGNUM * r, const BIGNUM * a, BN_CTX * ctx) { int ret = 0; BN_CTX *ctx_new = NULL; if (!group || !r || !a) { ECerr(EC_F_EC_GFP_NIST_FIELD_SQR, EC_R_PASSED_NULL_PARAMETER); goto err; } if (!ctx) if ((ctx_new = ctx = BN_CTX_new()) == NULL) goto err; if (!BN_sqr(r, a, ctx)) goto err; if (!group->field_mod_func(r, r, &group->field, ctx)) goto err; ret = 1; err: if (ctx_new) BN_CTX_free(ctx_new); return ret; }
int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y, BN_RECP_CTX *recp, BN_CTX *ctx) { int ret = 0; BIGNUM *a; const BIGNUM *ca; BN_CTX_start(ctx); if ((a = BN_CTX_get(ctx)) == NULL) goto err; if (y != NULL) { if (x == y) { if (!BN_sqr(a, x, ctx)) goto err; } else { if (!BN_mul(a, x, y, ctx)) goto err; } ca = a; } else ca = x; /* Just do the mod */ ret = BN_div_recp(NULL, r, ca, recp, ctx); err: BN_CTX_end(ctx); bn_check_top(r); return ret; }
int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) { int i, bits, ret = 0; BIGNUM *v, *rr; if ((p->flags & BN_FLG_CONSTTIME) != 0) { /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } BN_CTX_start(ctx); if (r == a || r == p) { rr = BN_CTX_get(ctx); } else { rr = r; } v = BN_CTX_get(ctx); if (rr == NULL || v == NULL) { goto err; } if (BN_copy(v, a) == NULL) { goto err; } bits = BN_num_bits(p); if (BN_is_odd(p)) { if (BN_copy(rr, a) == NULL) { goto err; } } else { if (!BN_one(rr)) { goto err; } } for (i = 1; i < bits; i++) { if (!BN_sqr(v, v, ctx)) { goto err; } if (BN_is_bit_set(p, i)) { if (!BN_mul(rr, rr, v, ctx)) { goto err; } } } if (r != rr && !BN_copy(r, rr)) { goto err; } ret = 1; err: BN_CTX_end(ctx); return ret; }
void openssl_bioBN_math() { BIO *outs; BN_CTX *ctx; char num1[8], num2[8]; BIGNUM *bg1, *bg2, *tmp, *stp; bg1 = BN_new(); bg2 = BN_new(); tmp = BN_new(); ctx = BN_CTX_new(); strcpy(num1, "84"); strcpy(num2, "3"); BN_hex2bn(&bg1, num1); BN_hex2bn(&bg2, num2); outs = BIO_new(BIO_s_file()); BIO_set_fp(outs, stdout, BIO_NOCLOSE); printf("\nBIO_MATH as follow:\n"); BN_add(tmp, bg1, bg2); BIO_puts(outs, "\tbn(0x84 + 0x3) = 0x"); BN_print(outs, tmp); BIO_puts(outs, "\n"); BN_sub(tmp, bg1, bg2); BIO_puts(outs, "\tbn(0x84 - 0x3) = 0x"); BN_print(outs, tmp); BIO_puts(outs, "\n"); BN_mul(tmp, bg1, bg2, ctx); BIO_puts(outs, "\tbn(0x84 * 0x3) = 0x"); BN_print(outs, tmp); BIO_puts(outs, "\n"); BN_sqr(tmp, bg1, ctx); BIO_puts(outs, "\tbn(sqr(0x84)) = 0x"); BN_print(outs, tmp); BIO_puts(outs, "\n"); BN_div(tmp, stp, bg1, bg2, ctx); BIO_puts(outs, "\tbn(0x84 / 0x3) = 0x"); BN_print(outs, tmp); BIO_puts(outs, "\n"); BN_exp(tmp, bg1, bg2, ctx); BIO_puts(outs, "\tbn(0x84 e 0x03)= 0x"); BN_print(outs, tmp); BIO_puts(outs, "\n"); BN_free(bg1); BN_free(bg2); BN_free(tmp); BIO_free(outs); }
/* * pr_fact - print the factors of a number * * If the number is 0 or 1, then print the number and return. * If the number is < 0, print -1, negate the number and continue * processing. * * Print the factors of the number, from the lowest to the highest. * A factor will be printed numtiple times if it divides the value * multiple times. * * Factors are printed with leading tabs. */ static void pr_fact(BIGNUM *val) { const ubig *fact; /* The factor found. */ /* Firewall - catch 0 and 1. */ if (BN_is_zero(val) || BN_is_one(val)) errx(1, "numbers <= 1 aren't permitted."); /* Factor value. */ BN_print_dec_fp(stdout, val); putchar(':'); for (fact = &prime[0]; !BN_is_one(val); ++fact) { /* Look for the smallest factor. */ while (fact <= pr_limit) { if (BN_mod_word(val, (BN_ULONG)*fact) == 0) break; fact++; } /* Watch for primes larger than the table. */ if (fact > pr_limit) { #ifdef HAVE_OPENSSL BIGNUM *bnfact; bnfact = BN_new(); BN_set_word(bnfact, (BN_ULONG)*(fact - 1)); BN_sqr(bnfact, bnfact, ctx); if (BN_cmp(bnfact, val) > 0 || BN_is_prime(val, PRIME_CHECKS, NULL, NULL, NULL) == 1) { putchar(' '); BN_print_dec_fp(stdout, val); } else pollard_rho(val); #else printf(" %s", BN_bn2dec(val)); #endif break; } /* Divide factor out until none are left. */ do { printf(" %lu", *fact); BN_div_word(val, (BN_ULONG)*fact); } while (BN_mod_word(val, (BN_ULONG)*fact) == 0); /* Let the user know we're doing something. */ fflush(stdout); } putchar('\n'); }
static RSA * fermat_question_ask(const RSA *rsa) { BIGNUM *a = BN_new(), *b = BN_new(), *a2 = BN_new(), *b2 = BN_new(); BIGNUM *n = rsa->n; BIGNUM *tmp = BN_new(), *rem = BN_new(), *dssdelta = BN_new(); BN_CTX *ctx = BN_CTX_new(); RSA *ret = NULL; BN_sqrtmod(tmp, rem, n, ctx); /* Δ = |p - q| = |a + b - a + b| = |2b| > √N 2⁻¹⁰⁰ */ /* BN_rshift(dssdelta, tmp, 101); */ BN_one(dssdelta); BN_lshift(dssdelta, dssdelta, BN_num_bits(n) / 4 + 10); BN_copy(a, tmp); BN_sqr(a2, a, ctx); do { /* a² += 2a + 1 */ BN_lshift1(tmp, a); BN_uiadd1(tmp); BN_add(a2, a2, tmp); /* a += 1 */ BN_uiadd1(a); /* b² = a² - N */ BN_usub(b2, a2, n); /* b */ BN_sqrtmod(b, rem, b2, ctx); } while (!BN_is_zero(rem) && BN_cmp(b, dssdelta) < 1); if (BN_is_zero(rem)) { BN_uadd(a, a, b); ret = qa_RSA_recover(rsa, a, ctx); } BN_CTX_free(ctx); BN_free(a); BN_free(b); BN_free(a2); BN_free(b2); BN_free(dssdelta); BN_free(tmp); BN_free(rem); return ret; }
void do_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) { int i, j, k; double tm; long num; for (i = 0; i < NUM_SIZES; i++) { num = BASENUM; if (i) num /= (i * 3); BN_rand(a, sizes[i], 1, 0); for (j = i; j < NUM_SIZES; j++) { BN_rand(b, sizes[j], 1, 0); Time_F(START); for (k = 0; k < num; k++) BN_mul(r, b, a, ctx); tm = Time_F(STOP); /*printf("mul %4d x %4d -> %8.3fms\n", sizes[i], sizes[j], tm * 1000.0 / num);*//* LEVANCIO S10 comment delete R.Miura 2016/02/03 */ } } for (i = 0; i < NUM_SIZES; i++) { num = BASENUM; if (i) num /= (i * 3); BN_rand(a, sizes[i], 1, 0); Time_F(START); for (k = 0; k < num; k++) BN_sqr(r, a, ctx); tm = Time_F(STOP); /*printf("sqr %4d x %4d -> %8.3fms\n", sizes[i], sizes[i], tm * 1000.0 / num);*//* LEVANCIO S10 comment delete R.Miura 2016/02/03 */ } for (i = 0; i < NUM_SIZES; i++) { num = BASENUM / 10; if (i) num /= (i * 3); BN_rand(a, sizes[i] - 1, 1, 0); for (j = i; j < NUM_SIZES; j++) { BN_rand(b, sizes[j], 1, 0); Time_F(START); for (k = 0; k < 100000; k++) BN_div(r, NULL, b, a, ctx); tm = Time_F(STOP); /*printf("div %4d / %4d -> %8.3fms\n", sizes[j], sizes[i] - 1, tm * 1000.0 / num);*//* LEVANCIO S10 comment delete R.Miura 2016/02/03 */ } } }
void do_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) { int i,j,k; double tm; long num; for (i=0; i<NUM_SIZES; i++) { num=BASENUM; if (i) num/=(i*3); BN_rand(a,sizes[i],1,0); for (j=i; j<NUM_SIZES; j++) { BN_rand(b,sizes[j],1,0); Time_F(START); for (k=0; k<num; k++) BN_mul(r,b,a,ctx); tm=Time_F(STOP); TINYCLR_SSL_FPRINTF("mul %4d x %4d -> %8.3fms\n",sizes[i],sizes[j],tm*1000.0/num); } } for (i=0; i<NUM_SIZES; i++) { num=BASENUM; if (i) num/=(i*3); BN_rand(a,sizes[i],1,0); Time_F(START); for (k=0; k<num; k++) BN_sqr(r,a,ctx); tm=Time_F(STOP); TINYCLR_SSL_FPRINTF("sqr %4d x %4d -> %8.3fms\n",sizes[i],sizes[i],tm*1000.0/num); } for (i=0; i<NUM_SIZES; i++) { num=BASENUM/10; if (i) num/=(i*3); BN_rand(a,sizes[i]-1,1,0); for (j=i; j<NUM_SIZES; j++) { BN_rand(b,sizes[j],1,0); Time_F(START); for (k=0; k<100000; k++) BN_div(r, NULL, b, a,ctx); tm=Time_F(STOP); TINYCLR_SSL_FPRINTF("div %4d / %4d -> %8.3fms\n",sizes[j],sizes[i]-1,tm*1000.0/num); } } }
int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_MONT_CTX *mont, BN_CTX *ctx) { BIGNUM *tmp; int ret = 0; int num = mont->N.top; #if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD) if (num > 1 && a->top == num && b->top == num) { if (bn_wexpand(r, num) == NULL) return (0); if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) { r->neg = a->neg ^ b->neg; r->top = num; r->flags |= BN_FLG_FIXED_TOP; return (1); } } #endif if ((a->top + b->top) > 2 * num) return 0; BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); if (tmp == NULL) goto err; bn_check_top(tmp); if (a == b) { if (!BN_sqr(tmp, a, ctx)) goto err; } else { if (!BN_mul(tmp, a, b, ctx)) goto err; } /* reduce from aRR to aR */ #ifdef MONT_WORD if (!bn_from_montgomery_word(r, tmp, mont)) goto err; #else if (!BN_from_montgomery(r, tmp, mont, ctx)) goto err; #endif ret = 1; err: BN_CTX_end(ctx); return (ret); }
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BN_MONT_CTX *mont, BN_CTX *ctx) { BIGNUM *tmp; int ret = 0; #if defined(OPENSSL_BN_ASM_MONT) int num = mont->N.top; if (num > 1 && a->top == num && b->top == num) { if (bn_wexpand(r, num) == NULL) { return 0; } if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) { r->neg = a->neg ^ b->neg; r->top = num; bn_correct_top(r); return 1; } } #endif BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); if (tmp == NULL) { goto err; } if (a == b) { if (!BN_sqr(tmp, a, ctx)) { goto err; } } else { if (!BN_mul(tmp, a, b, ctx)) { goto err; } } /* reduce from aRR to aR */ if (!BN_from_montgomery_word(r, tmp, mont)) { goto err; } ret = 1; err: BN_CTX_end(ctx); return ret; }
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BN_MONT_CTX *mont, BN_CTX *ctx) { BIGNUM *tmp; int ret = 0; int num = mont->N.top; /* bn_mul_mont requires at least four limbs, at least for x86. */ if (num >= 4 && a->top == num && b->top == num) { if (bn_wexpand(r, num) == NULL) { return 0; } bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num); r->neg = a->neg ^ b->neg; r->top = num; bn_correct_top(r); return 1; } BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); if (tmp == NULL) { goto err; } if (a == b) { if (!BN_sqr(tmp, a, ctx)) { goto err; } } else { if (!BN_mul(tmp, a, b, ctx)) { goto err; } } /* reduce from aRR to aR */ if (!BN_from_montgomery_word(r, tmp, mont)) { goto err; } ret = 1; err: BN_CTX_end(ctx); return ret; }
int test_sqr(BIO *bp, BN_CTX *ctx) { BIGNUM a,c,d,e; int i; BN_init(&a); BN_init(&c); BN_init(&d); BN_init(&e); for (i=0; i<num0; i++) { BN_bntest_rand(&a,40+i*10,0,0); a.neg=rand_neg(); BN_sqr(&c,&a,ctx); if (bp != NULL) { if (!results) { BN_print(bp,&a); BIO_puts(bp," * "); BN_print(bp,&a); BIO_puts(bp," - "); } BN_print(bp,&c); BIO_puts(bp,"\n"); } BN_div(&d,&e,&c,&a,ctx); BN_sub(&d,&d,&a); if(!BN_is_zero(&d) || !BN_is_zero(&e)) { fprintf(stderr,"Square test failed!\n"); return 0; } } BN_free(&a); BN_free(&c); BN_free(&d); BN_free(&e); return(1); }
int BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *x, BIGNUM *y, BN_RECP_CTX *recp, BN_CTX *ctx) { int ret=0; BIGNUM *a; BN_CTX_start(ctx); if ((a = BN_CTX_get(ctx)) == NULL) goto err; if (y != NULL) { if (x == y) { if (!BN_sqr(a,x,ctx)) goto err; } else { if (!BN_mul(a,x,y,ctx)) goto err; } } else a=x; /* Just do the mod */ BN_div_recp(NULL,r,a,recp,ctx); ret=1; err: BN_CTX_end(ctx); return(ret); }
static void pollard_rho(BIGNUM *val) { BIGNUM *x, *y, *tmp, *num; BN_ULONG a; unsigned int steps_taken, steps_limit; x = BN_new(); y = BN_new(); tmp = BN_new(); num = BN_new(); a = 1; restart: steps_taken = 0; steps_limit = 2; BN_set_word(x, 1); BN_copy(y, x); for (;;) { BN_sqr(tmp, x, ctx); BN_add_word(tmp, a); BN_mod(x, tmp, val, ctx); BN_sub(tmp, x, y); if (BN_is_zero(tmp)) { #ifdef DEBUG printf(" (loop)"); #endif a++; goto restart; } BN_gcd(tmp, tmp, val, ctx); if (!BN_is_one(tmp)) { if (BN_is_prime(tmp, PRIME_CHECKS, NULL, NULL, NULL) == 1) { putchar(' '); BN_print_dec_fp(stdout, tmp); } else { #ifdef DEBUG printf(" (recurse for "); BN_print_dec_fp(stdout, tmp); putchar(')'); #endif pollard_rho(BN_dup(tmp)); #ifdef DEBUG printf(" (back)"); #endif } fflush(stdout); BN_div(num, NULL, val, tmp, ctx); if (BN_is_one(num)) return; if (BN_is_prime(num, PRIME_CHECKS, NULL, NULL, NULL) == 1) { putchar(' '); BN_print_dec_fp(stdout, num); fflush(stdout); return; } BN_copy(val, num); goto restart; } steps_taken++; if (steps_taken == steps_limit) { BN_copy(y, x); /* teleport the turtle */ steps_taken = 0; steps_limit *= 2; if (steps_limit == 0) { #ifdef DEBUG printf(" (overflow)"); #endif a++; goto restart; } } } }
int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) { if (!BN_sqr(r, (BIGNUM*)a, ctx)) return 0; return BN_mod(r, r, m, ctx); }
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 RSA_recover_crt_params(RSA *rsa) { BN_CTX *ctx; BIGNUM *totient, *rem, *multiple, *p_plus_q, *p_minus_q; int ok = 0; if (rsa->n == NULL || rsa->e == NULL || rsa->d == NULL) { OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, RSA_R_EMPTY_PUBLIC_KEY); return 0; } if (rsa->p || rsa->q || rsa->dmp1 || rsa->dmq1 || rsa->iqmp) { OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, RSA_R_CRT_PARAMS_ALREADY_GIVEN); return 0; } /* This uses the algorithm from section 9B of the RSA paper: * http://people.csail.mit.edu/rivest/Rsapaper.pdf */ ctx = BN_CTX_new(); if (ctx == NULL) { OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, ERR_R_MALLOC_FAILURE); return 0; } BN_CTX_start(ctx); totient = BN_CTX_get(ctx); rem = BN_CTX_get(ctx); multiple = BN_CTX_get(ctx); p_plus_q = BN_CTX_get(ctx); p_minus_q = BN_CTX_get(ctx); if (totient == NULL || rem == NULL || multiple == NULL || p_plus_q == NULL || p_minus_q == NULL) { OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, ERR_R_MALLOC_FAILURE); goto err; } /* ed-1 is a small multiple of φ(n). */ if (!BN_mul(totient, rsa->e, rsa->d, ctx) || !BN_sub_word(totient, 1) || /* φ(n) = * pq - p - q + 1 = * n - (p + q) + 1 * * Thus n is a reasonable estimate for φ(n). So, (ed-1)/n will be very * close. But, when we calculate the quotient, we'll be truncating it * because we discard the remainder. Thus (ed-1)/multiple will be >= n, * which the totient cannot be. So we add one to the estimate. * * Consider ed-1 as: * * multiple * (n - (p+q) + 1) = * multiple*n - multiple*(p+q) + multiple * * When we divide by n, the first term becomes multiple and, since * multiple and p+q is tiny compared to n, the second and third terms can * be ignored. Thus I claim that subtracting one from the estimate is * sufficient. */ !BN_div(multiple, NULL, totient, rsa->n, ctx) || !BN_add_word(multiple, 1) || !BN_div(totient, rem, totient, multiple, ctx)) { OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, ERR_R_BN_LIB); goto err; } if (!BN_is_zero(rem)) { OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, RSA_R_BAD_RSA_PARAMETERS); goto err; } rsa->p = BN_new(); rsa->q = BN_new(); rsa->dmp1 = BN_new(); rsa->dmq1 = BN_new(); rsa->iqmp = BN_new(); if (rsa->p == NULL || rsa->q == NULL || rsa->dmp1 == NULL || rsa->dmq1 == NULL || rsa->iqmp == NULL) { OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, ERR_R_MALLOC_FAILURE); goto err; } /* φ(n) = n - (p + q) + 1 => * n - totient + 1 = p + q */ if (!BN_sub(p_plus_q, rsa->n, totient) || !BN_add_word(p_plus_q, 1) || /* p - q = sqrt((p+q)^2 - 4n) */ !BN_sqr(rem, p_plus_q, ctx) || !BN_lshift(multiple, rsa->n, 2) || !BN_sub(rem, rem, multiple) || !BN_sqrt(p_minus_q, rem, ctx) || /* q is 1/2 (p+q)-(p-q) */ !BN_sub(rsa->q, p_plus_q, p_minus_q) || !BN_rshift1(rsa->q, rsa->q) || !BN_div(rsa->p, NULL, rsa->n, rsa->q, ctx) || !BN_mul(multiple, rsa->p, rsa->q, ctx)) { OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, ERR_R_BN_LIB); goto err; } if (BN_cmp(multiple, rsa->n) != 0) { OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, RSA_R_INTERNAL_ERROR); goto err; } if (!BN_sub(rem, rsa->p, BN_value_one()) || !BN_mod(rsa->dmp1, rsa->d, rem, ctx) || !BN_sub(rem, rsa->q, BN_value_one()) || !BN_mod(rsa->dmq1, rsa->d, rem, ctx) || !BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx)) { OPENSSL_PUT_ERROR(RSA, RSA_recover_crt_params, ERR_R_BN_LIB); goto err; } ok = 1; err: BN_CTX_end(ctx); BN_CTX_free(ctx); if (!ok) { bn_free_and_null(&rsa->p); bn_free_and_null(&rsa->q); bn_free_and_null(&rsa->dmp1); bn_free_and_null(&rsa->dmq1); bn_free_and_null(&rsa->iqmp); } return ok; }
int BN_sqrt(BIGNUM *out_sqrt, const BIGNUM *in, BN_CTX *ctx) { BIGNUM *estimate, *tmp, *delta, *last_delta, *tmp2; int ok = 0, last_delta_valid = 0; if (in->neg) { OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); return 0; } if (BN_is_zero(in)) { BN_zero(out_sqrt); return 1; } BN_CTX_start(ctx); if (out_sqrt == in) { estimate = BN_CTX_get(ctx); } else { estimate = out_sqrt; } tmp = BN_CTX_get(ctx); last_delta = BN_CTX_get(ctx); delta = BN_CTX_get(ctx); if (estimate == NULL || tmp == NULL || last_delta == NULL || delta == NULL) { OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); goto err; } // We estimate that the square root of an n-bit number is 2^{n/2}. if (!BN_lshift(estimate, BN_value_one(), BN_num_bits(in)/2)) { goto err; } // This is Newton's method for finding a root of the equation |estimate|^2 - // |in| = 0. for (;;) { // |estimate| = 1/2 * (|estimate| + |in|/|estimate|) if (!BN_div(tmp, NULL, in, estimate, ctx) || !BN_add(tmp, tmp, estimate) || !BN_rshift1(estimate, tmp) || // |tmp| = |estimate|^2 !BN_sqr(tmp, estimate, ctx) || // |delta| = |in| - |tmp| !BN_sub(delta, in, tmp)) { OPENSSL_PUT_ERROR(BN, ERR_R_BN_LIB); goto err; } delta->neg = 0; // The difference between |in| and |estimate| squared is required to always // decrease. This ensures that the loop always terminates, but I don't have // a proof that it always finds the square root for a given square. if (last_delta_valid && BN_cmp(delta, last_delta) >= 0) { break; } last_delta_valid = 1; tmp2 = last_delta; last_delta = delta; delta = tmp2; } if (BN_cmp(tmp, in) != 0) { OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE); goto err; } ok = 1; err: if (ok && out_sqrt == in && !BN_copy(out_sqrt, estimate)) { ok = 0; } BN_CTX_end(ctx); return ok; }