//B_t, B_t*を生成 basis tfel_linear_transformation(const matrix *D, const basis A, const EC_GROUP g) { int i, j; EC_POINT temp1, temp2, temp3; EC_POINT *temp; temp = (EC_POINT*)malloc(sizeof(EC_POINT)*D->dim); for(i = 0; i < D->dim; i++) { point_init(temp[i], g); } point_init(temp1, g); point_init(temp2, g); point_init(temp3, g); point_set_infinity(temp2); //matrix *B; basis B; B.dim = D->dim; B.M = (EC_POINT**)malloc(sizeof(EC_POINT*)*D->dim); for(i = 0; i < D->dim; i++) { B.M[i] = (EC_POINT*)malloc(sizeof(EC_POINT)*D->dim); for(j = 0; j < D->dim; j++) { point_init(B.M[i][j], g); } } for(i = 0; i < D->dim; i++) { for(j = 0; j < D->dim; j++) { point_mul(B.M[i][j], D->M[i][j], A.M[i][i]); } } return B; }
//============================================ // MAP to POINT テスト //============================================ void test_map_to_point(const EC_GROUP ec) { int i; unsigned long long int t1, t2; EC_POINT P, Q; point_init(P, ec); point_init(Q, ec); point_map_to_point(P, MAP_STR, sizeof(MAP_STR), t); assert(point_is_on_curve(P)); point_mul(Q, ec->order, P); assert(point_is_infinity(Q)); point_map_to_point(Q, MAP_STR, sizeof(MAP_STR), t); assert(point_cmp(Q, P) == 0); t1 = rdtsc(); for (i = 0; i < M; i++) { point_map_to_point(P, MAP_STR, sizeof(MAP_STR), t); } t2 = rdtsc(); printf("point map to point in 128 security: %.2lf [clock]\n", (double)(t2 - t1) / M); point_clear(P); point_clear(Q); }
static int check_ecdsa(struct point *Q, u8 *R, u8 *S, u8 *hash) { u8 Sinv[21]; u8 e[21]; u8 w1[21], w2[21]; struct point r1, r2; u8 rr[21]; e[0] = 0; memcpy(e + 1, hash, 20); bn_reduce(e, ec_N, 21); bn_to_mon(R, ec_N, 21); bn_to_mon(S, ec_N, 21); bn_to_mon(e, ec_N, 21); bn_mon_inv(Sinv, S, ec_N, 21); bn_mon_mul(w1, e, Sinv, ec_N, 21); bn_mon_mul(w2, R, Sinv, ec_N, 21); bn_from_mon(w1, ec_N, 21); bn_from_mon(w2, ec_N, 21); point_mul(&r1, w1, &ec_G); point_mul(&r2, w2, Q); point_add(&r1, &r1, &r2); point_from_mon(&r1); rr[0] = 0; memcpy(rr + 1, r1.x, 20); bn_reduce(rr, ec_N, 21); bn_from_mon(R, ec_N, 21); bn_from_mon(S, ec_N, 21); return (bn_compare(rr, R, 21) == 0); }
// shared_secret_out is a pointer to 0x3c long buffer // remote_public_key is a pointer to the remote party's public key (0x3c bytes) // NG_priv is the device-unique private key to use // if NG_priv is nullptr, default builtin will be used void get_shared_secret(u8* shared_secret_out, u8* remote_public_key, u8* NG_priv) { if (NG_priv==nullptr) { NG_priv = default_NG_priv; } // required point_mul in Source/Core/Common/Crypto/ec.cpp // to be made non-static point_mul(shared_secret_out, NG_priv, remote_public_key); }
static void generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash) { u8 e[21]; u8 kk[21]; u8 m[21]; u8 minv[21]; struct point mG; FILE *fp; e[0] = 0; memcpy(e + 1, hash, 20); bn_reduce(e, ec_N, 21); try_again: fp = fopen("/dev/random", "rb"); if (fread(m, sizeof m, 1, fp) != 1) fail("reading random"); fclose(fp); m[0] = 0; if (bn_compare(m, ec_N, 21) >= 0) goto try_again; // R = (mG).x point_mul(&mG, m, &ec_G); point_from_mon(&mG); R[0] = 0; elt_copy(R+1, mG.x); // S = m**-1*(e + Rk) (mod N) bn_copy(kk, k, 21); bn_reduce(kk, ec_N, 21); bn_to_mon(m, ec_N, 21); bn_to_mon(e, ec_N, 21); bn_to_mon(R, ec_N, 21); bn_to_mon(kk, ec_N, 21); bn_mon_mul(S, R, kk, ec_N, 21); bn_add(kk, S, e, ec_N, 21); bn_mon_inv(minv, m, ec_N, 21); bn_mon_mul(S, minv, kk, ec_N, 21); bn_from_mon(R, ec_N, 21); bn_from_mon(S, ec_N, 21); }
static void generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash) { u8 e[21]; u8 kk[21]; u8 m[21]; u8 minv[21]; struct point mG; e[0] = 0; memcpy(e + 1, hash, 20); bn_reduce(e, ec_N, 21); try_again: get_rand(m, sizeof m); m[0] = 0; if (bn_compare(m, ec_N, 21) >= 0) goto try_again; // R = (mG).x point_mul(&mG, m, &ec_G); point_from_mon(&mG); R[0] = 0; elt_copy(R+1, mG.x); // S = m**-1*(e + Rk) (mod N) bn_copy(kk, k, 21); bn_reduce(kk, ec_N, 21); bn_to_mon(m, ec_N, 21); bn_to_mon(e, ec_N, 21); bn_to_mon(R, ec_N, 21); bn_to_mon(kk, ec_N, 21); bn_mon_mul(S, R, kk, ec_N, 21); bn_add(kk, S, e, ec_N, 21); bn_mon_inv(minv, m, ec_N, 21); bn_mon_mul(S, minv, kk, ec_N, 21); bn_from_mon(R, ec_N, 21); bn_from_mon(S, ec_N, 21); }
void IBE_extract_byte_string(byte_string_t bs, byte_string_t master, byte_string_t id, params_t params) //for testing purposes { point_t key; mpz_t x; mpz_init(x); point_init(key); map_byte_string_to_point(key, id, params); mympz_set_byte_string(x, master); point_mul(key, x, key, params->curve); byte_string_set_point(bs, key); point_clear(key); mpz_clear(x); }
void IBE_extract_share_byte_string(byte_string_t share, byte_string_t mshare, byte_string_t id, params_t params) //extract a private key share from an ID and master share { mpz_t y; int i; byte_string_t bs1, bs2; point_t yd; point_t d; point_init(yd); point_init(d); mpz_init(y); byte_string_split(bs1, bs2, mshare); i = int_from_byte_string(bs1); mympz_set_byte_string(y, bs2); byte_string_clear(bs1); byte_string_clear(bs2); map_byte_string_to_point(d, id, params); point_mul(yd, y, d, params->curve); byte_string_set_int(bs1, i); byte_string_set_point(bs2, yd); byte_string_join(share, bs1, bs2); byte_string_clear(bs1); byte_string_clear(bs2); point_clear(yd); point_clear(d); mpz_clear(y); }
static void ec_priv_to_pub(u8 *k, u8 *Q) { point_mul(Q, k, ec_G); }
void IBE_split_master(byte_string_t *mshare, byte_string_t master, int t, int n, params_t params) //split the master key into n pieces //t of them are required to generate a key { mpz_t * poly = malloc(sizeof(mpz_t)*t); mpz_t *x; mpz_t *y = malloc(sizeof(mpz_t)*n); mpz_t z; mpz_t r; int i, j; byte_string_t bs1, bs2; //start with random polynomial with degree <= t-2 //(in F_q) //whose constant term = master mpz_init(r); mpz_init(poly[0]); mympz_set_byte_string(poly[0], master); for (i=1; i<t; i++) { mpz_init(poly[i]); mympz_randomm(r, params->q); mpz_set(poly[i], r); } mpz_init(z); if (0) { printf("secret poly: "); for (i=0; i<t; i++) { printf(" "); mpz_out_str(NULL, 0, poly[i]); } printf("\n"); } params->robustx = (mpz_t *) malloc(n * sizeof(mpz_t)); params->robustP = (point_t *) malloc(n * sizeof(point_t)); params->sharet = t; params->sharen = n; x = params->robustx; for (i=0; i<n; i++) { mympz_randomm(r, params->q); mpz_init(x[i]); mpz_set(x[i], r); //Horner's rule mpz_set_ui(z, 0); for (j=t-1; j>=0; j--) { mpz_mul(z, z, x[i]); mpz_add(z, z, poly[j]); mpz_mod(z, z, params->q); } mpz_init_set(y[i], z); byte_string_set_int(bs1, i); byte_string_set_mpz(bs2, z); byte_string_join(mshare[i], bs1, bs2); byte_string_clear(bs1); byte_string_clear(bs2); } for (i=0; i<n; i++) { point_init(params->robustP[i]); point_mul(params->robustP[i], y[i], params->Ppub, params->curve); } for (i=0; i<t; i++) { mpz_clear(poly[i]); } for (i=0; i<n; i++) { mpz_clear(y[i]); } mpz_clear(z); mpz_clear(r); }
int IBE_combine(byte_string_t key, byte_string_t *kshare, params_t params) //reconstruct a key from key shares, or a certificate from certificate shares { int i, j; int indexi, indexj; point_t yP; mpz_t num, denom; mpz_t z; point_t d; byte_string_t bs1, bs2; int *index; index = (int *) malloc(params->sharet * sizeof(int)); for (i=0; i<params->sharet; i++) { byte_string_split(bs1, bs2, kshare[i]); byte_string_clear(bs2); index[i] = int_from_byte_string(bs1); byte_string_clear(bs1); for (j=0; j<i; j++) { if (index[i] == index[j]) { return 0; } } } point_init(yP); mpz_init(z); mpz_init(num); mpz_init(denom); point_init(d); point_set_O(d); for (i=0; i<params->sharet; i++) { byte_string_split(bs1, bs2, kshare[i]); indexi = index[i]; byte_string_clear(bs1); point_set_byte_string(yP, bs2); byte_string_clear(bs2); mpz_set_ui(num, 1); mpz_set_ui(denom, 1); for (j=0; j<params->sharet; j++) { if (j != i) { indexj = index[j]; mpz_mul(num, num, params->robustx[indexj]); mpz_mod(num, num, params->q); mpz_sub(z, params->robustx[indexj], params->robustx[indexi]); mpz_mul(denom, denom, z); mpz_mod(denom, denom, params->q); } } mpz_invert(denom, denom, params->q); mpz_mul(z, num, denom); mpz_mod(z, z, params->q); point_mul(yP, z, yP, params->curve); point_add(d, d, yP, params->curve); } byte_string_set_point(key, d); point_clear(yP); mpz_clear(z); mpz_clear(num); mpz_clear(denom); point_clear(d); return 1; }
void IBE_setup(params_t params, byte_string_t master, int k, int qk, char *id) /* generate system parameters * k = number of bits in p (should be at least 512) * qk = number of bits in q (size of subgroup, 160 is typical) * id = system ID */ { mpz_t p, q, r; mpz_t x; point_ptr P; int solinasa, solinasb; int kqk = k - qk - 4; //lose 4 bits since 12 is a 4-bit no. unsigned int seed; mpz_init(p); mpz_init(q); mpz_init(r); mpz_init(x); //find random k-bit prime p such that //p = 2 mod 3 and q = (p+1)/12r is prime as well for some r //now also want q to be a Solinas prime //we use rand() to help us find one: should be ok crypto_rand_bytes((unsigned char *) &seed, sizeof(int)); srand(seed); for(;;) { //once q was just a random qk-bit prime //now it must be a Solinas one mpz_set_ui(q, 0); solinasa = qk - 1; mpz_setbit(q, solinasa); mpz_set_ui(r, 0); solinasb = rand() % qk; mpz_setbit(r, solinasb); if (rand() % 2) { mpz_add(q, q, r); } else { mpz_sub(q, q, r); solinasb = -solinasb; } mpz_set_ui(r, 1); if (rand() % 2) { mpz_add(q, q, r); } else { mpz_sub(q, q, r); solinasa = -solinasa; } if (!mpz_probab_prime_p(q, 10)) continue; mympz_randomb(r, kqk); //p = q * r mpz_mul(p, q, r); //r = (((p << 1) + p) << 2) (= 12p) mpz_mul_2exp(r, p, 1); mpz_add(r, r, p); mpz_mul_2exp(r, r, 2); //p = r - 1 mpz_set_ui(p, 1); mpz_sub(p, r, p); if (mpz_probab_prime_p(p, 10)) break; } //pick master key x from F_q mympz_randomm(x, q); byte_string_set_mpz(master, x); mpz_init(params->p); mpz_init(params->q); mpz_set(params->p, p); mpz_set(params->q, q); initpq(params); //pick random point P of order q from E/F_p point_init(params->P); P = params->P; do { point_random(P, params->curve); point_make_order_q(P, params); } while (P->infinity); point_init(params->Ppub); point_mul(params->Ppub, x, P, params->curve); point_mul_preprocess(P, params->curve); miller_cache_init(params->Ppub_mc, params->curve); tate_preprocess(params->Ppub_mc, params->Ppub, params->curve); point_init(params->PhiPpub); point_Phi(params->PhiPpub, params->Ppub, params); params->id = (char *) malloc(strlen(id) + 1); strcpy(params->id, id); params->sharet = params->sharen = 0; params->version = (char *) malloc(strlen(IBE_VERSION) + 1); strcpy(params->version, IBE_VERSION); mpz_clear(p); mpz_clear(q); mpz_clear(r); mpz_clear(x); }
static void point_make_order_q(point_t P, params_t params) //P = ((p + 1)/q)P //so it has order q { point_mul(P, params->p1onq, P, params->curve); }
//============================================ // 楕円曲線の演算テスト //============================================ void test_arithmetic_operation(const EC_GROUP ec) { int i; unsigned long long int t1, t2; EC_POINT a, b, c, d; Element dx, dy; mpz_t scalar; //------------------- // init //------------------- point_init(a, ec); point_init(b, ec); point_init(c, ec); point_init(d, ec); //------------------- // random //------------------- point_random(a); assert(point_is_on_curve(a)); t1 = rdtsc(); for (i = 0; i < M; i++) { point_random(a); } t2 = rdtsc(); printf("point random: %.2lf [clock]\n", (double)(t2 - t1) / M); //------------------- // add/dob //------------------- point_add(b, b, a); point_add(c, b, c); assert(point_cmp(b, a) == 0); assert(point_cmp(c, b) == 0); point_set_infinity(d); point_dob(d, d); assert(point_is_infinity(d)); point_set_str(a, "[6D2E4115FA177379A504A0EE4EF53767DE51C6364AAB69D4064529EC1FD047A 635B2C858AA4F4A3DB8AA17A588B037CAFFD36678F76E3F3369DFC90C6878C7,193E877C82EFCA81EC2815906630B837BBC6976CC8A7958E6A40D1B190FF2E5F E8A77E88AFCEE9F806DC15BF50EADD138320F1A5A87E78DDE86FA7A867300D]"); point_set_str(b, "[1A8F5DAB09EE4290F95FE4C824C153E355D55B6CF94B998C6203FEC3D81377CF 15A19F2704C4BDBAAE39A5E26772A3E4E7EC7A9E205651F8822298766DE044FF,1C566EB3917F06B05E0A786BD8030CAFCCDB62864DD0E2A22A9B6817B310FD53 6A0927BB33EB263F45CAB921A20E67A1BD8A791D6EB0415AC92C9B1F74D16D1]"); point_set_str(d, "[143D414F99AA18C844B331064C9DD66363EBA3D852250CBCF8C9D4B33E0C4C1C 225865D85EC7A34647CA55E026BD1FA201E0C4E8C66F7A43E69AF708F410A0FF,FACA1388C034CF614A72E06EE60DEDC4880CDBD368E5BEC2795130B266FFB9E 1681217E50705AB9A21FEB62E0BF9A5657EB27C3AED3323FE9C57058358735A9]"); point_add(c, a, b); assert(point_cmp(c, d) == 0); t1 = rdtsc(); for (i = 0; i < N; i++) { point_add(c, a, b); } t2 = rdtsc(); printf("point add: %.2lf [clock]\n", (double)(t2 - t1) / N); element_init(dx, ec->field); element_init(dy, ec->field); element_set_str(dx, "33F550F9A63EF53C786BF7BDFDAB1538CD76A3FCED3C9DBC3307DD4F354775A C814AE99C91C71845F0B51E4349520908E48C70181313D70C05F6ED24EC1F36"); element_set_str(dy, "3766ED0DD7C988DB76770081A298DAA924D0E3279726F9B5504129AFA3E57B9 520CE8A563F88AF882AB99086BFDBBDCEF9DE65879AB234DFF5AAFD5BEE7E4F"); point_set_xy(d, dx, dy); point_dob(c, a); assert(point_cmp(c, d) == 0); t1 = rdtsc(); for (i = 0; i < N; i++) { point_dob(c, a); } t2 = rdtsc(); printf("point dob: %.2lf [clock]\n", (double)(t2 - t1) / N); element_clear(dx); element_clear(dy); //------------------ // neg/sub //------------------ point_neg(c, a); point_add(d, a, c); point_sub(b, a, a); assert(point_is_infinity(d)); assert(point_is_infinity(b)); //------------------- // mul //------------------- mpz_init(scalar); mpz_set(scalar, ec->order); for (i = 0; i < 100; i++) { point_random(a); point_mul(b, scalar, a); ec_bn254_fp2_mul_end(c, scalar, a); assert(point_is_infinity(b)); assert(point_cmp(c, b) == 0); } t1 = rdtsc(); for (i = 0; i < M; i++) { point_mul(b, scalar, a); } t2 = rdtsc(); printf("point mul with endomorphism: %.2lf [clock]\n", (double)(t2 - t1) / M); t1 = rdtsc(); for (i = 0; i < M; i++) { ec_bn254_fp2_mul(b, scalar, a); } t2 = rdtsc(); printf("point mul with binary method: %.2lf [clock]\n", (double)(t2 - t1) / M); mpz_clear(scalar); //------------------- // clear //------------------- point_clear(a); point_clear(b); point_clear(c); point_clear(d); }