/* * test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success. */ static int test_exp_mod_zero() { BIGNUM a, p, m; BIGNUM r; BN_CTX *ctx = BN_CTX_new(); int ret = 1; BN_init(&m); BN_one(&m); BN_init(&a); BN_one(&a); BN_init(&p); BN_zero(&p); BN_init(&r); BN_mod_exp(&r, &a, &p, &m, ctx); BN_CTX_free(ctx); if (BN_is_zero(&r)) ret = 0; else { printf("1**0 mod 1 = "); BN_print_fp(stdout, &r); printf(", should be 0\n"); } BN_free(&r); BN_free(&a); BN_free(&p); BN_free(&m); return ret; }
BIGNUM * Polynomial::GetLagIntCoe(vector<int> *allParties,int index) { BN_CTX *ctx = BN_CTX_new(); BIGNUM *up = BN_new(); BN_one(up); BIGNUM *down = BN_new(); BN_one(down); vector<int>::iterator iter; for (iter=allParties->begin();iter!= allParties->end();iter++) { if(*iter == index) continue; BIGNUM *j = BN_int2bn(-(*iter)); BIGNUM *i_j = BN_int2bn(index-(*iter)); BN_mul(up,up,j,ctx); BN_mul(down,down,i_j,ctx); } BIGNUM * result = BN_new(); BN_mod_inverse(result,down,p,ctx); BN_mod_mul(result,result,up,p,ctx); BN_free(up); BN_free(down); BN_CTX_free(ctx); return result; }
void compute_y(BIGNUM *bn_y, BIGNUM *bn_a, BIGNUM *bn_r, BIGNUM *bn_n, BN_CTX *bn_ctx){ BIGNUM *bn_i = NULL; BIGNUM *bn_1 = NULL; int num_bits = 0; int i = 0; BIGNUM **bn_array = NULL; num_bits = BN_num_bits(bn_r); bn_array = (BIGNUM **)malloc(sizeof(BIGNUM*) * num_bits); computeBNArray(bn_array, bn_a, bn_n, bn_ctx, num_bits); bn_1 = BN_new(); bn_i = BN_new(); BN_one(bn_1); BN_zero(bn_i); BN_one(bn_y); for(i = 0; i < num_bits; i++){ if(BN_is_bit_set(bn_r, i) == 1){ BN_mod_mul(bn_y, bn_y, bn_array[i], bn_n, bn_ctx); } } BN_free(bn_1); BN_free(bn_i); }
// Extended Euclidean algorithm, Knuth's Algorithm X int bnem_xgcd (BIGNUM *rx, BIGNUM *ry, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { int result = 0; // default return value is failure BIGNUM x, y, lastx, lasty, q, r, t1, t2, wa, wb; BN_init (&x); BN_init (&y); BN_init (&lastx); BN_init (&lasty); BN_init (&q); BN_init (&r); BN_init (&t1); BN_init (&t2); BN_init (&wa); BN_init (&wb); if ( ! BN_copy (&wa, a)) goto err; if ( ! BN_copy (&wb, b)) goto err; /* x, lastx = 0, 1 y, lasty = 1, 0 while b: q, r = divmod (a, b) a, b = b, r x, lastx = (lastx - q*x), x y, lasty = (lasty - q*y), y return lastx, lasty */ BN_one (&lastx); BN_one (&y); while ( ! BN_is_zero (&wb)) { if ( ! BN_div (&q, &r, &wa, &wb, ctx)) goto err; if ( ! BN_copy (&wa, &wb)) goto err; if ( ! BN_copy (&wb, &r)) goto err; if ( ! BN_copy (&t1, &x)) goto err; if ( ! BN_mul (&t2, &q, &x, ctx)) goto err; if ( ! BN_sub (&x, &lastx, &t2)) goto err; if ( ! BN_copy (&lastx, &t1)) goto err; if ( ! BN_copy (&t1, &y)) goto err; if ( ! BN_mul (&t2, &q, &y, ctx)) goto err; if ( ! BN_sub (&y, &lasty, &t2)) goto err; if ( ! BN_copy (&lasty, &t1)) goto err; } if (rx) { if ( ! BN_copy (rx, &lastx)) goto err; } if (ry) { if ( ! BN_copy (ry, &lasty)) goto err; } result = 1; // result is success err: BN_clear_free (&x); BN_clear_free (&y); BN_clear_free (&lastx); BN_clear_free (&lasty); BN_clear_free (&q); BN_clear_free (&r); BN_clear_free (&t1); BN_clear_free (&t2); BN_clear_free (&wa); BN_clear_free (&wb); return result; } // bnem_xgcd
int test_exp(BIO *bp, BN_CTX *ctx) { BIGNUM *a,*b,*d,*e,*one; int i; a=BN_new(); b=BN_new(); d=BN_new(); e=BN_new(); one=BN_new(); BN_one(one); for (i=0; i<num2; i++) { BN_bntest_rand(a,20+i*5,0,0); /**/ BN_bntest_rand(b,2+i,0,0); /**/ if (!BN_exp(d,a,b,ctx)) return(00); if (bp != NULL) { if (!results) { BN_print(bp,a); BIO_puts(bp," ^ "); BN_print(bp,b); BIO_puts(bp," - "); } BN_print(bp,d); BIO_puts(bp,"\n"); } BN_one(e); for( ; !BN_is_zero(b) ; BN_sub(b,b,one)) BN_mul(e,e,a,ctx); BN_sub(e,e,d); if(!BN_is_zero(e)) { fprintf(stderr,"Exponentiation test failed!\n"); return 0; } } BN_free(a); BN_free(b); BN_free(d); BN_free(e); BN_free(one); return(1); }
/* Forces the given EC_POINT to internally use affine coordinates. */ int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BIGNUM *x, *y; int ret = 0; if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) return 1; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } BN_CTX_start(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); if (y == NULL) goto err; if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err; if (!BN_copy(&point->X, x)) goto err; if (!BN_copy(&point->Y, y)) goto err; if (!BN_one(&point->Z)) goto err; ret = 1; err: if (ctx) BN_CTX_end(ctx); if (new_ctx) BN_CTX_free(new_ctx); return ret; }
data_chunk deterministic_wallet::generate_public_key( size_t n, bool for_change) const { hash_digest sequence = get_sequence(n, for_change); ssl_bignum x, y, z; BN_bin2bn(sequence.data(), sequence.size(), z); BN_bin2bn(master_public_key_.data(), 32, x); BN_bin2bn(master_public_key_.data() + 32, 32, y); // Create a point. ec_group group(EC_GROUP_new_by_curve_name(NID_secp256k1)); ec_point mpk(EC_POINT_new(group)); bn_ctx ctx(BN_CTX_new()); EC_POINT_set_affine_coordinates_GFp(group, mpk, x, y, ctx); ec_point result(EC_POINT_new(group)); // result pubkey_point = mpk_pubkey_point + z*curve.generator ssl_bignum one; BN_one(one); EC_POINT_mul(group, result, z, mpk, one, ctx); // Create the actual public key. EC_POINT_get_affine_coordinates_GFp(group, result, x, y, ctx); // 04 + x + y data_chunk raw_pubkey{0x04}; extend_data(raw_pubkey, bignum_data(x)); extend_data(raw_pubkey, bignum_data(y)); return raw_pubkey; }
CHECK_RETVAL_BOOL \ static BOOLEAN selfTestGeneralOps1( void ) { BIGNUM a; /* Simple tests that don't need the support of higher-level routines like importBignum() */ BN_init( &a ); if( !BN_zero( &a ) ) return( FALSE ); if( !BN_is_zero( &a ) || BN_is_one( &a ) ) return( FALSE ); if( !BN_is_word( &a, 0 ) || BN_is_word( &a, 1 ) ) return( FALSE ); if( BN_is_odd( &a ) ) return( FALSE ); if( BN_get_word( &a ) != 0 ) return( FALSE ); if( !BN_one( &a ) ) return( FALSE ); if( BN_is_zero( &a ) || !BN_is_one( &a ) ) return( FALSE ); if( BN_is_word( &a, 0 ) || !BN_is_word( &a, 1 ) ) return( FALSE ); if( !BN_is_odd( &a ) ) return( FALSE ); if( BN_num_bytes( &a ) != 1 ) return( FALSE ); if( BN_get_word( &a ) != 1 ) return( FALSE ); BN_clear( &a ); return( TRUE ); }
int BN_solinas2bn(const BN_SOLINAS *solinas, BIGNUM *bn) { int ret = 0; BIGNUM *tmp = NULL; if (!solinas || !bn) { BNerr(BN_F_BN_SOLINAS2BN, ERR_R_MALLOC_FAILURE); return 0; } if (solinas->b <= 0 || solinas->a <= solinas->b || (solinas->s != 1 && solinas->s != -1) || (solinas->c != 1 && solinas->c != -1)) { BNerr(BN_F_BN_SOLINAS2BN, BN_R_INVALID_SOLINAS_PARAMETERS); return 0; } if (!(tmp = BN_new())) { BNerr(BN_F_BN_SOLINAS2BN, ERR_R_MALLOC_FAILURE); goto end; } BN_one(tmp); if (!BN_lshift(bn, tmp, solinas->a)) { BNerr(BN_F_BN_SOLINAS2BN, ERR_R_BN_LIB); goto end; } if (!BN_lshift(tmp, tmp, solinas->b)) { BNerr(BN_F_BN_SOLINAS2BN, ERR_R_BN_LIB); goto end; } if (!BN_add_word(tmp, solinas->c)) { BNerr(BN_F_BN_SOLINAS2BN, ERR_R_BN_LIB); goto end; } if (solinas->s > 0) { if (!BN_add(bn, bn, tmp)) { BNerr(BN_F_BN_SOLINAS2BN, ERR_R_BN_LIB); goto end; } } else { if (!BN_sub(bn, bn, tmp)) { BNerr(BN_F_BN_SOLINAS2BN, ERR_R_BN_LIB); goto end; } } /* check if it is a prime */ ret = 1; end: BN_free(tmp); return ret; }
/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2) * using Montgomery point multiplication algorithm Mxy() in appendix of * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over * GF(2^m) without precomputation" (CHES '99, LNCS 1717). * Returns: * 0 on error * 1 if return value should be the point at infinity * 2 otherwise */ static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y, BIGNUM *x1, BIGNUM *z1, BIGNUM *x2, BIGNUM *z2, BN_CTX *ctx) { BIGNUM *t3, *t4, *t5; int ret = 0; if (BN_is_zero(z1)) { BN_zero(x2); BN_zero(z2); return 1; } if (BN_is_zero(z2)) { if (!BN_copy(x2, x)) return 0; if (!BN_GF2m_add(z2, x, y)) return 0; return 2; } /* Since Mxy is static we can guarantee that ctx != NULL. */ BN_CTX_start(ctx); t3 = BN_CTX_get(ctx); t4 = BN_CTX_get(ctx); t5 = BN_CTX_get(ctx); if (t5 == NULL) goto err; if (!BN_one(t5)) goto err; if (!group->meth->field_mul(group, t3, z1, z2, ctx)) goto err; if (!group->meth->field_mul(group, z1, z1, x, ctx)) goto err; if (!BN_GF2m_add(z1, z1, x1)) goto err; if (!group->meth->field_mul(group, z2, z2, x, ctx)) goto err; if (!group->meth->field_mul(group, x1, z2, x1, ctx)) goto err; if (!BN_GF2m_add(z2, z2, x2)) goto err; if (!group->meth->field_mul(group, z2, z2, z1, ctx)) goto err; if (!group->meth->field_sqr(group, t4, x, ctx)) goto err; if (!BN_GF2m_add(t4, t4, y)) goto err; if (!group->meth->field_mul(group, t4, t4, t3, ctx)) goto err; if (!BN_GF2m_add(t4, t4, z2)) goto err; if (!group->meth->field_mul(group, t3, t3, x, ctx)) goto err; if (!group->meth->field_div(group, t3, t5, t3, ctx)) goto err; if (!group->meth->field_mul(group, t4, t3, t4, ctx)) goto err; if (!group->meth->field_mul(group, x2, x1, t3, ctx)) goto err; if (!BN_GF2m_add(z2, x2, x)) goto err; if (!group->meth->field_mul(group, z2, z2, t4, ctx)) goto err; if (!BN_GF2m_add(z2, z2, y)) goto err; ret = 2; err: BN_CTX_end(ctx); return ret; }
int test_lshift(BIO *bp,BN_CTX *ctx,BIGNUM *a_) { BIGNUM *a,*b,*c,*d; int i; b=BN_new(); c=BN_new(); d=BN_new(); BN_one(c); if(a_) a=a_; else { a=BN_new(); BN_bntest_rand(a,200,0,0); /**/ a->neg=rand_neg(); } for (i=0; i<num0; i++) { BN_lshift(b,a,i+1); BN_add(c,c,c); if (bp != NULL) { if (!results) { BN_print(bp,a); BIO_puts(bp," * "); BN_print(bp,c); BIO_puts(bp," - "); } BN_print(bp,b); BIO_puts(bp,"\n"); } BN_mul(d,a,c,ctx); BN_sub(d,d,b); if(!BN_is_zero(d)) { fprintf(stderr,"Left shift test failed!\n"); fprintf(stderr,"a="); BN_print_fp(stderr,a); fprintf(stderr,"\nb="); BN_print_fp(stderr,b); fprintf(stderr,"\nc="); BN_print_fp(stderr,c); fprintf(stderr,"\nd="); BN_print_fp(stderr,d); fprintf(stderr,"\n"); return 0; } } BN_free(a); BN_free(b); BN_free(c); BN_free(d); return(1); }
int gost_do_verify (const unsigned char *dgst, int dgst_len, DSA_SIG * sig, DSA * dsa) { BIGNUM *md, *tmp = NULL; BIGNUM *q2 = NULL; BIGNUM *u = NULL, *v = NULL, *z1 = NULL, *z2 = NULL; BIGNUM *tmp2 = NULL, *tmp3 = NULL; int ok; BN_CTX *ctx = BN_CTX_new (); BN_CTX_start (ctx); if (BN_cmp (sig->s, dsa->q) >= 1 || BN_cmp (sig->r, dsa->q) >= 1) { GOSTerr (GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); return 0; } md = hashsum2bn (dgst); tmp = BN_CTX_get (ctx); v = BN_CTX_get (ctx); q2 = BN_CTX_get (ctx); z1 = BN_CTX_get (ctx); z2 = BN_CTX_get (ctx); tmp2 = BN_CTX_get (ctx); tmp3 = BN_CTX_get (ctx); u = BN_CTX_get (ctx); BN_mod (tmp, md, dsa->q, ctx); if (BN_is_zero (tmp)) { BN_one (md); } BN_copy (q2, dsa->q); BN_sub_word (q2, 2); BN_mod_exp (v, md, q2, dsa->q, ctx); BN_mod_mul (z1, sig->s, v, dsa->q, ctx); BN_sub (tmp, dsa->q, sig->r); BN_mod_mul (z2, tmp, v, dsa->p, ctx); BN_mod_exp (tmp, dsa->g, z1, dsa->p, ctx); BN_mod_exp (tmp2, dsa->pub_key, z2, dsa->p, ctx); BN_mod_mul (tmp3, tmp, tmp2, dsa->p, ctx); BN_mod (u, tmp3, dsa->q, ctx); ok = BN_cmp (u, sig->r); BN_free (md); BN_CTX_end (ctx); BN_CTX_free (ctx); if (ok != 0) { GOSTerr (GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); } return (ok == 0); }
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; }
/* * test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success. */ static int test_exp_mod_zero() { BIGNUM *a = NULL, *p = NULL, *m = NULL; BIGNUM *r = NULL; BN_CTX *ctx = BN_CTX_new(); int ret = 1; m = BN_new(); if (!m) goto err; BN_one(m); a = BN_new(); if (!a) goto err; BN_one(a); p = BN_new(); if (!p) goto err; BN_zero(p); r = BN_new(); if (!r) goto err; BN_mod_exp(r, a, p, m, ctx); BN_CTX_free(ctx); if (BN_is_zero(r)) ret = 0; else { printf("1**0 mod 1 = "); BN_print_fp(stdout, r); printf(", should be 0\n"); } err: BN_free(r); BN_free(a); BN_free(p); BN_free(m); return ret; }
/** https://core.telegram.org/api/end-to-end says: "Both clients in a secret chat creation are to check that g, g_a and g_b are greater than one and smaller than p-1. Recommented checking that g_a and g_b are between 2^{2048-64} and p - 2^{2048-64} as well." */ qint32 CryptoUtils::checkCalculatedParams(const BIGNUM *gAOrB, const BIGNUM *g, const BIGNUM *p) { ASSERT(gAOrB); ASSERT(g); ASSERT(p); // 1) gAOrB and g greater than one and smaller than p-1 BIGNUM one; BN_init(&one); Utils::ensure(BN_one(&one)); BIGNUM *pMinusOne = BN_dup(p); Utils::ensure(BN_sub_word(pMinusOne, 1)); // check params greater than one if (BN_cmp(gAOrB, &one) <= 0) return -1; if (BN_cmp(g, &one) <= 0) return -1; // check params <= p-1 if (BN_cmp(gAOrB, pMinusOne) >= 0) return -1; if (BN_cmp(g, pMinusOne) >= 0) return -1; // 2) gAOrB between 2^{2048-64} and p - 2^{2048-64} quint64 expWord = 2048 - 64; BIGNUM exp; BN_init(&exp); Utils::ensure(BN_set_word(&exp, expWord)); BIGNUM base; BN_init(&base); Utils::ensure(BN_set_word(&base, 2)); // lowLimit = base ^ exp BIGNUM lowLimit; BN_init(&lowLimit); Utils::ensure(BN_exp(&lowLimit, &base, &exp, BN_ctx)); // highLimit = p - lowLimit BIGNUM highLimit; BN_init(&highLimit); BN_sub(&highLimit, p, &lowLimit); if (BN_cmp(gAOrB, &lowLimit) < 0) return -1; if (BN_cmp(gAOrB, &highLimit) > 0) return -1; BN_free(&one); BN_free(pMinusOne); BN_free(&exp); BN_free(&lowLimit); BN_free(&highLimit); delete g; delete gAOrB; delete p; return 0; }
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; }
/* * Computes signature and returns it as DSA_SIG structure */ DSA_SIG *gost_do_sign (const unsigned char *dgst, int dlen, DSA * dsa) { BIGNUM *k = NULL, *tmp = NULL, *tmp2 = NULL; DSA_SIG *newsig = DSA_SIG_new (); BIGNUM *md = hashsum2bn (dgst); /* check if H(M) mod q is zero */ BN_CTX *ctx = BN_CTX_new (); BN_CTX_start (ctx); if (!newsig) { GOSTerr (GOST_F_GOST_DO_SIGN, GOST_R_NO_MEMORY); goto err; } tmp = BN_CTX_get (ctx); k = BN_CTX_get (ctx); tmp2 = BN_CTX_get (ctx); BN_mod (tmp, md, dsa->q, ctx); if (BN_is_zero (tmp)) { BN_one (md); } do { do { /*Generate random number k less than q */ BN_rand_range (k, dsa->q); /* generate r = (a^x mod p) mod q */ BN_mod_exp (tmp, dsa->g, k, dsa->p, ctx); if (!(newsig->r)) newsig->r = BN_new (); BN_mod (newsig->r, tmp, dsa->q, ctx); } while (BN_is_zero (newsig->r)); /* generate s = (xr + k(Hm)) mod q */ BN_mod_mul (tmp, dsa->priv_key, newsig->r, dsa->q, ctx); BN_mod_mul (tmp2, k, md, dsa->q, ctx); if (!newsig->s) newsig->s = BN_new (); BN_mod_add (newsig->s, tmp, tmp2, dsa->q, ctx); } while (BN_is_zero (newsig->s)); err: BN_free (md); BN_CTX_end (ctx); BN_CTX_free (ctx); return newsig; }
int test_rshift(BIO *bp,BN_CTX *ctx) { BIGNUM *a,*b,*c,*d,*e; int i; a=BN_new(); b=BN_new(); c=BN_new(); d=BN_new(); e=BN_new(); BN_one(c); BN_bntest_rand(a,200,0,0); /**/ a->neg=rand_neg(); for (i=0; i<num0; i++) { BN_rshift(b,a,i+1); BN_add(c,c,c); if (bp != NULL) { if (!results) { BN_print(bp,a); BIO_puts(bp," / "); BN_print(bp,c); BIO_puts(bp," - "); } BN_print(bp,b); BIO_puts(bp,"\n"); } BN_div(d,e,a,c,ctx); BN_sub(d,d,b); if(!BN_is_zero(d)) { fprintf(stderr,"Right shift test failed!\n"); return 0; } } BN_free(a); BN_free(b); BN_free(c); BN_free(d); BN_free(e); return(1); }
void setup() { mod = BN_bin2bn( mod_buffer, /*len*/192, NULL ); // modOrder = ( mod - 1 ) / 2 BIGNUM* postSubtract = BN_new(); BIGNUM* oneBN = BN_new(); int ret = BN_one( oneBN ); if ( ret != 1 ) { printf( "setup: BN_one failed: %d", ret ); } ret = BN_sub( postSubtract, mod, oneBN ); // r = a - b if ( ret != 1 ) { printf( "setup: BN_sub failed: %d", ret ); } BN_clear_free( oneBN ); modOrder = BN_new(); ret = BN_rshift1( modOrder, postSubtract ); // r = a Ö 2 if ( ret != 1 ) { printf( "setup: BN_rshift1 failed: %d", ret ); } BN_clear_free( postSubtract ); g2 = BN_new(); g3 = BN_new(); c1 = BN_new(); c2 = BN_new(); d1 = BN_new(); d2 = BN_new(); g3a = BN_new(); // exponent used in step 1 gen = BN_new(); ret = BN_set_word( gen, 2 ); match = 0; }
/* * prime_totient(p,q,totient) * Euler totient function of n, under the assumption * that n = pq and p and q are prime * inputs: BIGNUM* p * BIGNUM* q * output: BIGNUM* totient * * return value: 0 if failure * 1 if success */ int prime_totient(BIGNUM* p, BIGNUM* q, BIGNUM* totient){ BIGNUM one; BN_init(&one); BN_one(&one); BIGNUM* temp_p = BN_dup(p); BIGNUM* temp_q = BN_dup(q); BN_sub_word(temp_p, 1); BN_sub_word(temp_q, 1); BN_CTX* ctx = BN_CTX_new(); BN_mul(totient, temp_p, temp_q, ctx); BN_free(temp_p); BN_free(temp_q); BN_CTX_free(ctx); return 1; }
BIGNUM * Polynomial::GetFunctionValue(BIGNUM *x) { BN_CTX *ctx = BN_CTX_new(); BIGNUM * value = BN_new() ; BN_copy(value,*(coefficients->begin())); BIGNUM * tmp = BN_new(); BIGNUM * tmpx = BN_new(); BN_one(tmpx); vector<BIGNUM *>::iterator iter; for (iter=coefficients->begin()+1;iter!= coefficients->end();iter++) { BN_mod_mul(tmpx,tmpx,x,p,ctx); BN_mod_mul(tmp,tmpx,*iter,p,ctx); BN_mod_add(value,tmp,value,p,ctx); } BN_free(tmp); BN_free(tmpx); BN_CTX_free(ctx); return value; }
bool CECKey::TweakPublic(const unsigned char vchTweak[32]) { bool ret = true; BN_CTX *ctx = BN_CTX_new(); BN_CTX_start(ctx); BIGNUM *bnTweak = BN_CTX_get(ctx); BIGNUM *bnOrder = BN_CTX_get(ctx); BIGNUM *bnOne = BN_CTX_get(ctx); const EC_GROUP *group = EC_KEY_get0_group(pkey); EC_GROUP_get_order(group, bnOrder, ctx); // what a grossly inefficient way to get the (constant) group order... BN_bin2bn(vchTweak, 32, bnTweak); if (BN_cmp(bnTweak, bnOrder) >= 0) ret = false; // extremely unlikely EC_POINT *point = EC_POINT_dup(EC_KEY_get0_public_key(pkey), group); BN_one(bnOne); EC_POINT_mul(group, point, bnTweak, point, bnOne, ctx); if (EC_POINT_is_at_infinity(group, point)) ret = false; // ridiculously unlikely EC_KEY_set_public_key(pkey, point); EC_POINT_free(point); BN_CTX_end(ctx); BN_CTX_free(ctx); return ret; }
/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse. * It does not contain branches that may leak sensitive information. */ static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL; BIGNUM local_A, local_B; BIGNUM *pA, *pB; BIGNUM *ret=NULL; int sign; bn_check_top(a); bn_check_top(n); BN_CTX_start(ctx); A = BN_CTX_get(ctx); B = BN_CTX_get(ctx); X = BN_CTX_get(ctx); D = BN_CTX_get(ctx); M = BN_CTX_get(ctx); Y = BN_CTX_get(ctx); T = BN_CTX_get(ctx); if (T == NULL) goto err; if (in == NULL) R=BN_new(); else R=in; if (R == NULL) goto err; BN_one(X); BN_zero(Y); if (BN_copy(B,a) == NULL) goto err; if (BN_copy(A,n) == NULL) goto err; A->neg = 0; if (B->neg || (BN_ucmp(B, A) >= 0)) { /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, * BN_div_no_branch will be called eventually. */ pB = &local_B; BN_with_flags(pB, B, BN_FLG_CONSTTIME); if (!BN_nnmod(B, pB, A, ctx)) goto err; } sign = -1; /* From B = a mod |n|, A = |n| it follows that * * 0 <= B < A, * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). */ while (!BN_is_zero(B)) { BIGNUM *tmp; /* * 0 < B < A, * (*) -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|) */ /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, * BN_div_no_branch will be called eventually. */ pA = &local_A; BN_with_flags(pA, A, BN_FLG_CONSTTIME); /* (D, M) := (A/B, A%B) ... */ if (!BN_div(D,M,pA,B,ctx)) goto err; /* Now * A = D*B + M; * thus we have * (**) sign*Y*a == D*B + M (mod |n|). */ tmp=A; /* keep the BIGNUM object, the value does not matter */ /* (A, B) := (B, A mod B) ... */ A=B; B=M; /* ... so we have 0 <= B < A again */ /* Since the former M is now B and the former B is now A, * (**) translates into * sign*Y*a == D*A + B (mod |n|), * i.e. * sign*Y*a - D*A == B (mod |n|). * Similarly, (*) translates into * -sign*X*a == A (mod |n|). * * Thus, * sign*Y*a + D*sign*X*a == B (mod |n|), * i.e. * sign*(Y + D*X)*a == B (mod |n|). * * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). * Note that X and Y stay non-negative all the time. */ if (!BN_mul(tmp,D,X,ctx)) goto err; if (!BN_add(tmp,tmp,Y)) goto err; M=Y; /* keep the BIGNUM object, the value does not matter */ Y=X; X=tmp; sign = -sign; } /* * The while loop (Euclid's algorithm) ends when * A == gcd(a,n); * we have * sign*Y*a == A (mod |n|), * where Y is non-negative. */ if (sign < 0) { if (!BN_sub(Y,n,Y)) goto err; } /* Now Y*a == A (mod |n|). */ if (BN_is_one(A)) { /* Y*a == 1 (mod |n|) */ if (!Y->neg && BN_ucmp(Y,n) < 0) { if (!BN_copy(R,Y)) goto err; } else { if (!BN_nnmod(R,Y,n,ctx)) goto err; } } else { BNerr(BN_F_BN_MOD_INVERSE_NO_BRANCH,BN_R_NO_INVERSE); goto err; } ret=R; err: if ((ret == NULL) && (in == NULL)) BN_free(R); BN_CTX_end(ctx); bn_check_top(ret); return(ret); }
BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) /* Returns 'ret' such that * ret^2 == a (mod p), * using the Tonelli/Shanks algorithm (cf. Henri Cohen, "A Course * in Algebraic Computational Number Theory", algorithm 1.5.1). * 'p' must be prime! */ { BIGNUM *ret = in; int err = 1; int r; BIGNUM *A, *b, *q, *t, *x, *y; int e, i, j; if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) { if (BN_abs_is_word(p, 2)) { if (ret == NULL) ret = BN_new(); if (ret == NULL) goto end; if (!BN_set_word(ret, BN_is_bit_set(a, 0))) { if (ret != in) BN_free(ret); return NULL; } bn_check_top(ret); return ret; } BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); return(NULL); } if (BN_is_zero(a) || BN_is_one(a)) { if (ret == NULL) ret = BN_new(); if (ret == NULL) goto end; if (!BN_set_word(ret, BN_is_one(a))) { if (ret != in) BN_free(ret); return NULL; } bn_check_top(ret); return ret; } BN_CTX_start(ctx); A = BN_CTX_get(ctx); b = BN_CTX_get(ctx); q = BN_CTX_get(ctx); t = BN_CTX_get(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); if (y == NULL) goto end; if (ret == NULL) ret = BN_new(); if (ret == NULL) goto end; /* A = a mod p */ if (!BN_nnmod(A, a, p, ctx)) goto end; /* now write |p| - 1 as 2^e*q where q is odd */ e = 1; while (!BN_is_bit_set(p, e)) e++; /* we'll set q later (if needed) */ if (e == 1) { /* The easy case: (|p|-1)/2 is odd, so 2 has an inverse * modulo (|p|-1)/2, and square roots can be computed * directly by modular exponentiation. * We have * 2 * (|p|+1)/4 == 1 (mod (|p|-1)/2), * so we can use exponent (|p|+1)/4, i.e. (|p|-3)/4 + 1. */ if (!BN_rshift(q, p, 2)) goto end; q->neg = 0; if (!BN_add_word(q, 1)) goto end; if (!BN_mod_exp(ret, A, q, p, ctx)) goto end; err = 0; goto vrfy; } if (e == 2) { /* |p| == 5 (mod 8) * * In this case 2 is always a non-square since * Legendre(2,p) = (-1)^((p^2-1)/8) for any odd prime. * So if a really is a square, then 2*a is a non-square. * Thus for * b := (2*a)^((|p|-5)/8), * i := (2*a)*b^2 * we have * i^2 = (2*a)^((1 + (|p|-5)/4)*2) * = (2*a)^((p-1)/2) * = -1; * so if we set * x := a*b*(i-1), * then * x^2 = a^2 * b^2 * (i^2 - 2*i + 1) * = a^2 * b^2 * (-2*i) * = a*(-i)*(2*a*b^2) * = a*(-i)*i * = a. * * (This is due to A.O.L. Atkin, * <URL: http://listserv.nodak.edu/scripts/wa.exe?A2=ind9211&L=nmbrthry&O=T&P=562>, * November 1992.) */ /* t := 2*a */ if (!BN_mod_lshift1_quick(t, A, p)) goto end; /* b := (2*a)^((|p|-5)/8) */ if (!BN_rshift(q, p, 3)) goto end; q->neg = 0; if (!BN_mod_exp(b, t, q, p, ctx)) goto end; /* y := b^2 */ if (!BN_mod_sqr(y, b, p, ctx)) goto end; /* t := (2*a)*b^2 - 1*/ if (!BN_mod_mul(t, t, y, p, ctx)) goto end; if (!BN_sub_word(t, 1)) goto end; /* x = a*b*t */ if (!BN_mod_mul(x, A, b, p, ctx)) goto end; if (!BN_mod_mul(x, x, t, p, ctx)) goto end; if (!BN_copy(ret, x)) goto end; err = 0; goto vrfy; } /* e > 2, so we really have to use the Tonelli/Shanks algorithm. * First, find some y that is not a square. */ if (!BN_copy(q, p)) goto end; /* use 'q' as temp */ q->neg = 0; i = 2; do { /* For efficiency, try small numbers first; * if this fails, try random numbers. */ if (i < 22) { if (!BN_set_word(y, i)) goto end; } else { if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) goto end; if (BN_ucmp(y, p) >= 0) { if (!(p->neg ? BN_add : BN_sub)(y, y, p)) goto end; } /* now 0 <= y < |p| */ if (BN_is_zero(y)) if (!BN_set_word(y, i)) goto end; } r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */ if (r < -1) goto end; if (r == 0) { /* m divides p */ BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); goto end; } } while (r == 1 && ++i < 82); if (r != -1) { /* Many rounds and still no non-square -- this is more likely * a bug than just bad luck. * Even if p is not prime, we should have found some y * such that r == -1. */ BNerr(BN_F_BN_MOD_SQRT, BN_R_TOO_MANY_ITERATIONS); goto end; } /* Here's our actual 'q': */ if (!BN_rshift(q, q, e)) goto end; /* Now that we have some non-square, we can find an element * of order 2^e by computing its q'th power. */ if (!BN_mod_exp(y, y, q, p, ctx)) goto end; if (BN_is_one(y)) { BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); goto end; } /* Now we know that (if p is indeed prime) there is an integer * k, 0 <= k < 2^e, such that * * a^q * y^k == 1 (mod p). * * As a^q is a square and y is not, k must be even. * q+1 is even, too, so there is an element * * X := a^((q+1)/2) * y^(k/2), * * and it satisfies * * X^2 = a^q * a * y^k * = a, * * so it is the square root that we are looking for. */ /* t := (q-1)/2 (note that q is odd) */ if (!BN_rshift1(t, q)) goto end; /* x := a^((q-1)/2) */ if (BN_is_zero(t)) /* special case: p = 2^e + 1 */ { if (!BN_nnmod(t, A, p, ctx)) goto end; if (BN_is_zero(t)) { /* special case: a == 0 (mod p) */ BN_zero(ret); err = 0; goto end; } else if (!BN_one(x)) goto end; } else { if (!BN_mod_exp(x, A, t, p, ctx)) goto end; if (BN_is_zero(x)) { /* special case: a == 0 (mod p) */ BN_zero(ret); err = 0; goto end; } } /* b := a*x^2 (= a^q) */ if (!BN_mod_sqr(b, x, p, ctx)) goto end; if (!BN_mod_mul(b, b, A, p, ctx)) goto end; /* x := a*x (= a^((q+1)/2)) */ if (!BN_mod_mul(x, x, A, p, ctx)) goto end; while (1) { /* Now b is a^q * y^k for some even k (0 <= k < 2^E * where E refers to the original value of e, which we * don't keep in a variable), and x is a^((q+1)/2) * y^(k/2). * * We have a*b = x^2, * y^2^(e-1) = -1, * b^2^(e-1) = 1. */ if (BN_is_one(b)) { if (!BN_copy(ret, x)) goto end; err = 0; goto vrfy; } /* find smallest i such that b^(2^i) = 1 */ i = 1; if (!BN_mod_sqr(t, b, p, ctx)) goto end; while (!BN_is_one(t)) { i++; if (i == e) { BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); goto end; } if (!BN_mod_mul(t, t, t, p, ctx)) goto end; } /* t := y^2^(e - i - 1) */ if (!BN_copy(t, y)) goto end; for (j = e - i - 1; j > 0; j--) { if (!BN_mod_sqr(t, t, p, ctx)) goto end; } if (!BN_mod_mul(y, t, t, p, ctx)) goto end; if (!BN_mod_mul(x, x, t, p, ctx)) goto end; if (!BN_mod_mul(b, b, y, p, ctx)) goto end; e = i; } vrfy: if (!err) { /* verify the result -- the input might have been not a square * (test added in 0.9.8) */ if (!BN_mod_sqr(x, ret, p, ctx)) err = 1; if (!err && 0 != BN_cmp(x, A)) { BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); err = 1; } } end: if (err) { if (ret != NULL && ret != in) { BN_clear_free(ret); } ret = NULL; } BN_CTX_end(ctx); bn_check_top(ret); return ret; }
BIGNUM *BN_mod_inverse(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL; BIGNUM *ret=NULL; int sign; if ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(n, BN_FLG_CONSTTIME) != 0)) { return BN_mod_inverse_no_branch(in, a, n, ctx); } bn_check_top(a); bn_check_top(n); BN_CTX_start(ctx); A = BN_CTX_get(ctx); B = BN_CTX_get(ctx); X = BN_CTX_get(ctx); D = BN_CTX_get(ctx); M = BN_CTX_get(ctx); Y = BN_CTX_get(ctx); T = BN_CTX_get(ctx); if (T == NULL) goto err; if (in == NULL) R=BN_new(); else R=in; if (R == NULL) goto err; BN_one(X); BN_zero(Y); if (BN_copy(B,a) == NULL) goto err; if (BN_copy(A,n) == NULL) goto err; A->neg = 0; if (B->neg || (BN_ucmp(B, A) >= 0)) { if (!BN_nnmod(B, B, A, ctx)) goto err; } sign = -1; /* From B = a mod |n|, A = |n| it follows that * * 0 <= B < A, * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). */ if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048))) { /* Binary inversion algorithm; requires odd modulus. * This is faster than the general algorithm if the modulus * is sufficiently small (about 400 .. 500 bits on 32-bit * sytems, but much more on 64-bit systems) */ int shift; while (!BN_is_zero(B)) { /* * 0 < B < |n|, * 0 < A <= |n|, * (1) -sign*X*a == B (mod |n|), * (2) sign*Y*a == A (mod |n|) */ /* Now divide B by the maximum possible power of two in the integers, * and divide X by the same value mod |n|. * When we're done, (1) still holds. */ shift = 0; while (!BN_is_bit_set(B, shift)) /* note that 0 < B */ { shift++; if (BN_is_odd(X)) { if (!BN_uadd(X, X, n)) goto err; } /* now X is even, so we can easily divide it by two */ if (!BN_rshift1(X, X)) goto err; } if (shift > 0) { if (!BN_rshift(B, B, shift)) goto err; } /* Same for A and Y. Afterwards, (2) still holds. */ shift = 0; while (!BN_is_bit_set(A, shift)) /* note that 0 < A */ { shift++; if (BN_is_odd(Y)) { if (!BN_uadd(Y, Y, n)) goto err; } /* now Y is even */ if (!BN_rshift1(Y, Y)) goto err; } if (shift > 0) { if (!BN_rshift(A, A, shift)) goto err; } /* We still have (1) and (2). * Both A and B are odd. * The following computations ensure that * * 0 <= B < |n|, * 0 < A < |n|, * (1) -sign*X*a == B (mod |n|), * (2) sign*Y*a == A (mod |n|), * * and that either A or B is even in the next iteration. */ if (BN_ucmp(B, A) >= 0) { /* -sign*(X + Y)*a == B - A (mod |n|) */ if (!BN_uadd(X, X, Y)) goto err; /* NB: we could use BN_mod_add_quick(X, X, Y, n), but that * actually makes the algorithm slower */ if (!BN_usub(B, B, A)) goto err; } else { /* sign*(X + Y)*a == A - B (mod |n|) */ if (!BN_uadd(Y, Y, X)) goto err; /* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */ if (!BN_usub(A, A, B)) goto err; } } } else { /* general inversion algorithm */ while (!BN_is_zero(B)) { BIGNUM *tmp; /* * 0 < B < A, * (*) -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|) */ /* (D, M) := (A/B, A%B) ... */ if (BN_num_bits(A) == BN_num_bits(B)) { if (!BN_one(D)) goto err; if (!BN_sub(M,A,B)) goto err; } else if (BN_num_bits(A) == BN_num_bits(B) + 1) { /* A/B is 1, 2, or 3 */ if (!BN_lshift1(T,B)) goto err; if (BN_ucmp(A,T) < 0) { /* A < 2*B, so D=1 */ if (!BN_one(D)) goto err; if (!BN_sub(M,A,B)) goto err; } else { /* A >= 2*B, so D=2 or D=3 */ if (!BN_sub(M,A,T)) goto err; if (!BN_add(D,T,B)) goto err; /* use D (:= 3*B) as temp */ if (BN_ucmp(A,D) < 0) { /* A < 3*B, so D=2 */ if (!BN_set_word(D,2)) goto err; /* M (= A - 2*B) already has the correct value */ } else { /* only D=3 remains */ if (!BN_set_word(D,3)) goto err; /* currently M = A - 2*B, but we need M = A - 3*B */ if (!BN_sub(M,M,B)) goto err; } } } else { if (!BN_div(D,M,A,B,ctx)) goto err; } /* Now * A = D*B + M; * thus we have * (**) sign*Y*a == D*B + M (mod |n|). */ tmp=A; /* keep the BIGNUM object, the value does not matter */ /* (A, B) := (B, A mod B) ... */ A=B; B=M; /* ... so we have 0 <= B < A again */ /* Since the former M is now B and the former B is now A, * (**) translates into * sign*Y*a == D*A + B (mod |n|), * i.e. * sign*Y*a - D*A == B (mod |n|). * Similarly, (*) translates into * -sign*X*a == A (mod |n|). * * Thus, * sign*Y*a + D*sign*X*a == B (mod |n|), * i.e. * sign*(Y + D*X)*a == B (mod |n|). * * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). * Note that X and Y stay non-negative all the time. */ /* most of the time D is very small, so we can optimize tmp := D*X+Y */ if (BN_is_one(D)) { if (!BN_add(tmp,X,Y)) goto err; } else { if (BN_is_word(D,2)) { if (!BN_lshift1(tmp,X)) goto err; } else if (BN_is_word(D,4)) { if (!BN_lshift(tmp,X,2)) goto err; } else if (D->top == 1) { if (!BN_copy(tmp,X)) goto err; if (!BN_mul_word(tmp,D->d[0])) goto err; } else { if (!BN_mul(tmp,D,X,ctx)) goto err; } if (!BN_add(tmp,tmp,Y)) goto err; } M=Y; /* keep the BIGNUM object, the value does not matter */ Y=X; X=tmp; sign = -sign; } } /* * The while loop (Euclid's algorithm) ends when * A == gcd(a,n); * we have * sign*Y*a == A (mod |n|), * where Y is non-negative. */ if (sign < 0) { if (!BN_sub(Y,n,Y)) goto err; } /* Now Y*a == A (mod |n|). */ if (BN_is_one(A)) { /* Y*a == 1 (mod |n|) */ if (!Y->neg && BN_ucmp(Y,n) < 0) { if (!BN_copy(R,Y)) goto err; } else { if (!BN_nnmod(R,Y,n,ctx)) goto err; } } else { BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE); goto err; } ret=R; err: if ((ret == NULL) && (in == NULL)) BN_free(R); BN_CTX_end(ctx); bn_check_top(ret); return(ret); }
int millerrabin(BIGNUM *bn_n, int maxitr, FILE *primesfile, int num_idnt){ int s = 0; BIGNUM *bn_r = NULL; BIGNUM *bn_n_1 = NULL; BN_CTX *bn_ctx = NULL; BIGNUM *bn_a = NULL; BIGNUM *bn_y = NULL; BIGNUM *bn_1 = NULL; int i = 0; int j = 0; bn_a = BN_new(); bn_y = BN_new(); bn_r = BN_new(); bn_1 = BN_new(); BN_one(bn_1); bn_ctx = BN_CTX_new(); bn_n_1 = BN_new(); BN_CTX_init(bn_ctx); fseek(primesfile, 0 ,SEEK_SET); s = compute_sr(bn_n, bn_r, bn_n_1, bn_ctx); if(s == -1){ return -1; } if(num_idnt == 0){ fprintf(stdout, "n = %s\n", BN_bn2dec(bn_n)); } printIndents(num_idnt); fprintf(stdout, " n-1 = %s\n", BN_bn2dec(bn_n_1)); printIndents(num_idnt); fprintf(stdout, " s = %d\n", s); printIndents(num_idnt); fprintf(stdout, " r = %s\n", BN_bn2dec(bn_r)); for(i = 1; i <= maxitr; i++){ printIndents(num_idnt); fprintf(stdout, " Itr %d of %d, ", i, maxitr); ithPrime(i, primesfile, bn_a); if(BN_cmp(bn_a, bn_n_1) == 1){ return -1; } compute_y(bn_y, bn_a, bn_r, bn_n, bn_ctx); if(BN_cmp(bn_y, bn_1) != 0 && BN_cmp(bn_y, bn_n_1) != 0){ fprintf(stdout, "a = %s, y = %s\n", BN_bn2dec(bn_a), BN_bn2dec(bn_y)); for(j = 1; j <= s - 1; j++){ BN_mod_mul(bn_y, bn_y, bn_y, bn_n, bn_ctx); printIndents(num_idnt); fprintf(stdout, " j = %d of %d, y = %s", j, s - 1, BN_bn2dec(bn_y)); if(BN_cmp(bn_y, bn_n_1) == 0){ fprintf(stdout, " (which is n-1)\n"); break; } putchar('\n'); if(BN_cmp(bn_y, bn_1) == 0){ return 0; } } if(BN_cmp(bn_y, bn_n_1) != 0){ printIndents(num_idnt); fprintf(stdout, "Miller-Rabin found a strong witness %s\n", BN_bn2dec(bn_a)); return 0; } } else{ if(BN_cmp(bn_y, bn_n_1) == 0){ fprintf(stdout, "a = %s, y = %s (which is n-1)\n", BN_bn2dec(bn_a), BN_bn2dec(bn_y)); } else{ fprintf(stdout, "a = %s, y = %s\n", BN_bn2dec(bn_a), BN_bn2dec(bn_y)); } } } printIndents(num_idnt); fprintf(stdout, "Miller-Rabin declares n to be a prime number\n"); return 1; BN_free(bn_1); BN_free(bn_a); BN_free(bn_y); BN_free(bn_r); BN_CTX_free(bn_ctx); }
/* ------------------------------------------------------------------ */ int eg_decode (char *s, char *private_key, char **result) { // there is no any padding processing in the decoding routine // (see comment in rsa_encode) BIGNUM message, *gamma, *delta, k, temp1, temp2, one; BIGNUM *p=NULL, *g=NULL, *key=NULL; int i, nl, nc, rc1, rc2, rc3, length, index; unsigned char *buf = NULL; BN_CTX *ctx = NULL; char *p1, *p2, *p3; // setup key (p, g, key) p1 = strdup (private_key); p2 = strchr (p1, ':'); if (p2 == NULL) {free (p1); return -1;} *p2 = '\0'; p3 = strchr (p1, ','); if (p3 == NULL) { index = atoi (p1); if (index > sizeof(precomp)/sizeof(precomp[0])-1) return -1; p = NULL; rc1 = BN_hex2bn (&p, precomp[index].prime); if (rc1 == 0) return -1; g = BN_new (); if (g == NULL) return -1; BN_set_word (g, precomp[index].generator); } else { rc1 = BN_hex2bn (&p, p1); rc2 = BN_hex2bn (&g, p3+1); if (rc1 == 0 || rc2 == 0) return -1; } rc3 = BN_hex2bn (&key, p2+1); free (p1); if (rc3 == 0) return -1; // initialize temp variables BN_init (&message); BN_init (&k); BN_init (&temp1); BN_init (&temp2); BN_init (&one); BN_one (&one); gamma = BN_new (); if (gamma == NULL) return -1; delta = BN_new (); if (delta == NULL) return -1; ctx = BN_CTX_new (); if (ctx == NULL) return -1; // number of bytes in the modulus. this is the amount of bytes // we can convert in one gulp and should expect to be in one // group nl = BN_num_bytes (p); buf = malloc (nl); if (buf == NULL) return -1; // find the number of pieces in the encrypted message (the last // piece is not terminated with space) nc = str_numchars (s, ' ') + 1; // preallocate output buffer length = nc * nl; *result = malloc (length); if (*result == NULL) return -1; // cycle by pieces of input, each piece is 'nl' bytes long // (except the last one) p1 = s; for (i=0; i<nc; i++) { // extract next piece p2 = strchr (p1, ' '); if (p2 == NULL) { if (i != nc-1) return -1; } else { *p2 = '\0'; } p3 = strchr (p1, ','); if (p3 == NULL) return -1; *p3++ = '\0'; // convert to bignum rc1 = BN_hex2bn (&gamma, p1); if (rc1 == 0) return -1; rc1 = BN_hex2bn (&delta, p3); if (rc1 == 0) return -1; // ElGamal BN_sub (&temp1, p, &one); BN_sub (&temp2, &temp1, key); BN_mod_exp (&temp1, gamma, &temp2, p, ctx); BN_mod_mul (&message, &temp1, delta, p, ctx); // convert into binary output BN_bn2bin (&message, (unsigned char *)(*result+i*nl)); // advance pointer to prepare search for next piece p1 = p2 + 1; } BN_CTX_free (ctx); memset (buf, 0, nl); free(buf); return length; }
/* Computes scalar*point and stores the result in r. * point can not equal r. * Uses a modified algorithm 2P of * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over * GF(2^m) without precomputation" (CHES '99, LNCS 1717). * * To protect against side-channel attack the function uses constant time swap, * avoiding conditional branches. */ static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, const EC_POINT *point, BN_CTX *ctx) { BIGNUM *x1, *x2, *z1, *z2; int ret = 0, i; BN_ULONG mask,word; if (r == point) { ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT); return 0; } /* if result should be point at infinity */ if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) || EC_POINT_is_at_infinity(group, point)) { return EC_POINT_set_to_infinity(group, r); } /* only support affine coordinates */ if (!point->Z_is_one) return 0; /* Since point_multiply is static we can guarantee that ctx != NULL. */ BN_CTX_start(ctx); x1 = BN_CTX_get(ctx); z1 = BN_CTX_get(ctx); if (z1 == NULL) goto err; x2 = &r->X; z2 = &r->Y; bn_wexpand(x1, group->field.top); bn_wexpand(z1, group->field.top); bn_wexpand(x2, group->field.top); bn_wexpand(z2, group->field.top); if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) goto err; /* x1 = x */ if (!BN_one(z1)) goto err; /* z1 = 1 */ if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2 = x^2 */ if (!group->meth->field_sqr(group, x2, z2, ctx)) goto err; if (!BN_GF2m_add(x2, x2, &group->b)) goto err; /* x2 = x^4 + b */ /* find top most bit and go one past it */ i = scalar->top - 1; mask = BN_TBIT; word = scalar->d[i]; while (!(word & mask)) mask >>= 1; mask >>= 1; /* if top most bit was at word break, go to next word */ if (!mask) { i--; mask = BN_TBIT; } for (; i >= 0; i--) { word = scalar->d[i]; while (mask) { BN_consttime_swap(word & mask, x1, x2, group->field.top); BN_consttime_swap(word & mask, z1, z2, group->field.top); if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err; if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err; BN_consttime_swap(word & mask, x1, x2, group->field.top); BN_consttime_swap(word & mask, z1, z2, group->field.top); mask >>= 1; } mask = BN_TBIT; } /* convert out of "projective" coordinates */ i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx); if (i == 0) goto err; else if (i == 1) { if (!EC_POINT_set_to_infinity(group, r)) goto err; } else { if (!BN_one(&r->Z)) goto err; r->Z_is_one = 1; } /* GF(2^m) field elements should always have BIGNUM::neg = 0 */ BN_set_negative(&r->X, 0); BN_set_negative(&r->Y, 0); ret = 1; err: BN_CTX_end(ctx); return ret; }
static void runtest(const char *json_base_fn, const char *ser_in_fn, const char *block_in_hash, const char *tx_in_hash) { /* read wallet data */ char *json_fn = test_filename(json_base_fn); json_t *wallet = read_json(json_fn); assert(wallet != NULL); /* read block data containing incoming payment */ char *fn = test_filename(ser_in_fn); void *data; size_t data_len; assert(bu_read_file(fn, &data, &data_len, 1 * 1024 * 1024) == true); struct bp_block block_in; bp_block_init(&block_in); struct const_buffer buf = { data, data_len }; assert(deser_bp_block(&block_in, &buf) == true); bp_block_calc_sha256(&block_in); /* verify block-in data matches expected block-in hash */ bu256_t check_hash; assert(hex_bu256(&check_hash, block_in_hash) == true); assert(bu256_equal(&block_in.sha256, &check_hash) == true); /* load key that has received an incoming payment */ struct bp_key key; assert(bp_key_init(&key) == true); load_json_key(wallet, &key); /* load key into keyset */ struct bp_keyset ks; bpks_init(&ks); assert(bpks_add(&ks, &key) == true); /* find key matches in block */ parr *matches; matches = bp_block_match(&block_in, &ks); assert(matches != NULL); assert(matches->len == 1); struct bp_block_match *match = parr_idx(matches, 0); assert(match->n == 1); /* match 2nd tx, index 1 */ /* get matching transaction */ struct bp_tx *tx = parr_idx(block_in.vtx, match->n); bp_tx_calc_sha256(tx); /* verify txid matches expected */ char tx_hexstr[BU256_STRSZ]; bu256_hex(tx_hexstr, &tx->sha256); assert(strcmp(tx_hexstr, tx_in_hash) == 0); /* verify mask matches 2nd txout (1 << 1) */ BIGNUM tmp_mask; BN_init(&tmp_mask); BN_one(&tmp_mask); BN_lshift(&tmp_mask, &tmp_mask, 1); assert(BN_cmp(&tmp_mask, &match->mask) == 0); /* build merkle tree, tx's branch */ parr *mtree = bp_block_merkle_tree(&block_in); assert(mtree != NULL); parr *mbranch = bp_block_merkle_branch(&block_in, mtree, match->n); assert(mbranch != NULL); /* verify merkle branch for tx matches expected */ bu256_t mrk_check; bp_check_merkle_branch(&mrk_check, &tx->sha256, mbranch, match->n); assert(bu256_equal(&mrk_check, &block_in.hashMerkleRoot) == true); /* release resources */ parr_free(mtree, true); parr_free(mbranch, true); BN_clear_free(&tmp_mask); parr_free(matches, true); bpks_free(&ks); bp_key_free(&key); bp_block_free(&block_in); json_decref(wallet); free(data); free(fn); free(json_fn); }
void printnumber(FILE *f, const struct number *b, u_int base) { struct number *int_part, *fract_part; int digits; char buf[11]; size_t sz; int i; struct stack stack; char *p; charcount = 0; lastchar = -1; if (BN_is_zero(b->number)) putcharwrap(f, '0'); int_part = new_number(); fract_part = new_number(); fract_part->scale = b->scale; if (base <= 16) digits = 1; else { digits = snprintf(buf, sizeof(buf), "%u", base-1); } split_number(b, int_part->number, fract_part->number); i = 0; stack_init(&stack); while (!BN_is_zero(int_part->number)) { BN_ULONG rem = BN_div_word(int_part->number, base); stack_pushstring(&stack, get_digit(rem, digits, base)); i++; } sz = i; if (BN_cmp(b->number, &zero) < 0) putcharwrap(f, '-'); for (i = 0; i < sz; i++) { p = stack_popstring(&stack); if (base > 16) putcharwrap(f, ' '); printwrap(f, p); free(p); } stack_clear(&stack); if (b->scale > 0) { struct number *num_base; BIGNUM mult, stop; putcharwrap(f, '.'); num_base = new_number(); BN_set_word(num_base->number, base); BN_init(&mult); BN_one(&mult); BN_init(&stop); BN_one(&stop); scale_number(&stop, b->scale); i = 0; while (BN_cmp(&mult, &stop) < 0) { u_long rem; if (i && base > 16) putcharwrap(f, ' '); i = 1; bmul_number(fract_part, fract_part, num_base); split_number(fract_part, int_part->number, NULL); rem = BN_get_word(int_part->number); p = get_digit(rem, digits, base); int_part->scale = 0; normalize(int_part, fract_part->scale); BN_sub(fract_part->number, fract_part->number, int_part->number); printwrap(f, p); free(p); BN_mul_word(&mult, base); } free_number(num_base); BN_free(&mult); BN_free(&stop); } flushwrap(f); free_number(int_part); free_number(fract_part); }