size_t pbgp_ibe_serialized_signature_size(ibe_signature_t *signature) { return (size_t) element_length_in_bytes(signature->u) + element_length_in_bytes(signature->w) + element_length_in_bytes(signature->v); }
void Hmki(element_t* out, public_key pk, element_t* key) { // pk and key check element_init_Zr(*out, pairing); int len = (pk.level + 1) * sizeof(unsigned int) / sizeof(char); element_t x; element_init_G1(x,pairing); element_from_hash(x, pk.ID_tuple, len); len = element_length_in_bytes(x); unsigned char* str = (unsigned char* ) malloc(len); element_to_bytes(str, x); int len1 = element_length_in_bytes(*key); unsigned char* key_str = (unsigned char*) malloc(len1); element_to_bytes(key_str, *key); unsigned char* sum = (unsigned char*) malloc(len1 + len); memcpy(sum, str, len); memcpy(sum + len, key_str, len1); element_clear(x); free(str); free(key_str); unsigned char o[MD5_DIGEST_LENGTH + 1]; MD5(sum, len + len1, o); o[MD5_DIGEST_LENGTH] = '\0'; element_from_hash(*out, o, MD5_DIGEST_LENGTH); ///////////////////////// }
/** * @param buf must be allocated by caller * pbgp_ibe_serialized_signature_size() bytes long */ unsigned char * pbgp_ibe_signature_serialize(ibe_signature_t *signature, unsigned char *buf) { // Ugly as we recalculate size but still faster than malloc int u_len = element_length_in_bytes(signature->u), v_len = element_length_in_bytes(signature->v); element_to_bytes(buf, signature->u); element_to_bytes(buf + u_len, signature->v); element_to_bytes(buf + u_len + v_len, signature->w); return buf; }
// USER JOIN PHASE 4 - user key generation (Join) int xsgs_user_join_phase4(XSGS_PUBLIC_KEY* gpk, XSGS_USER_DB_ENTRY* udbe, XSGS_JOIN_PHASE3* jpd3, XSGS_JOIN_PHASE4* jpd4, char* upk_pem_filename) { int ret; pairing_ptr pairing = gpk->pairing; field_ptr Fp = pairing->Zr; DWORD msg_len = element_length_in_bytes(udbe->UCert.A); BYTE* msg = (BYTE*) malloc(msg_len); element_to_bytes(msg, udbe->UCert.A); /* TODO Verify_PK_CA(cert_user) */ ret = xsgs_rsa_verify(upk_pem_filename, msg, msg_len, jpd3->S.sig, jpd3->S.len); free(msg); udbe->S.len = jpd3->S.len; udbe->S.sig = (BYTE*) malloc(udbe->S.len); memcpy(udbe->S.sig, jpd3->S.sig, udbe->S.len); element_init(jpd4->x, Fp); element_set(jpd4->x, udbe->UCert.x); return ret; }
/* * Returns the length of the given element in bytes. * We assume that elements from G1 and G2 can be compressed, while elements from GT can't. */ int BilinearMappingHandler::getElementLengthInBytes(element_t elem, bool isElementOfGT) { if (isElementOfGT) return element_length_in_bytes(elem); //members of GT can't be compressed else return element_length_in_bytes_compressed(elem); //members of G1/G2 can be compressed }//end of getElementLengthInByte()
int newepoch_gen(char *out,epoch_item_t *ep,setup_params_t *setup) { char *accstr = NULL; int elem_size = 0; //update the accumulator acc_update(ep->acc,ep->epls.act,ep->epls.rvk,setup); ep->epoch++; //sign epoch revoked list sign_list_rsa(ep->s_rvk,setup,ep->epls.rvk); //sign epoch added list sign_list_rsa(ep->s_new,setup,ep->epls.act); elem_size = element_length_in_bytes(ep->acc->elem); accstr = (char *) malloc(elem_size); if(!accstr) { pbgp_error("newepoch :: %s\n",strerror(errno)); return -1; } element_snprintf(accstr,elem_size,"%B",ep->acc->elem); //sign accumulator value sign_rsa(ep->s_acc,setup,(uint8_t *)accstr); //dump envelope newepoch_save(out,ep,setup); free(accstr); return 0; }
//H_mki function from the article //unique hash function from bit string to Z_r //like HAMC H_A(mk_i | MD5(X | mk_i)) where H_A is H_3, mk_i = key void H_4(element_t* out, element_t key, char* string ) { int buff_size; //key to string; int element_length = element_length_in_bytes(key); if (strlen(string) < MD5_DIGEST_LENGTH ) { buff_size = MD5_DIGEST_LENGTH + element_length; } else { buff_size = strlen(string) + element_length; } unsigned char element_in_bytes[element_length + 1]; element_to_bytes(element_in_bytes, key); element_in_bytes[element_length] = '\0'; //concatanation X | mk_i := buff char buff[buff_size]; strcpy(buff, string); strcpy(buff + strlen(string), element_in_bytes); buff[strlen(string) + element_length] = '\0'; // compute MD5 of buff; unsigned char hash[MD5_DIGEST_LENGTH + 1]; MD5(buff, strlen(string) + element_length, hash); hash[MD5_DIGEST_LENGTH] = '\0'; //mk_i | hash to buff strcpy(buff, element_in_bytes); strcpy(buff + element_length, hash); buff[element_length + MD5_DIGEST_LENGTH] = '\0'; //compute H_A := H3 to get elemenet from Z_r H_3(*out, buff, element_length + MD5_DIGEST_LENGTH ); }
/** * Memoized version of element_from_hash * for performance reason */ static inline void _element_from_hash(element_t e, void *data, int len) { // @fixme: store is "left open" when executable close static store_t *store = NULL; if (!store) { store = pbgp_store_open(NULL); } store_key_t key = { 0, 0, len, (unsigned char *) data }; size_t size = 0; int ret = 0; if (0 == pbgp_store_uget_size(store, &key, &size)) { unsigned char buf[size]; memset (buf, 0, size); pbgp_store_uget(store, &key, buf, &size); ret = element_from_bytes(e, buf); } if (0 == ret) { element_from_hash(e, data, len); unsigned char edata[element_length_in_bytes(e)]; element_to_bytes(edata, e); pbgp_store_put(store, &key, edata, sizeof(edata)); } }
static inline void out(element_t elem, FILE *myfile) { int sz = element_length_in_bytes(elem); fwrite(&sz, 4, 1, myfile); unsigned char* data = pbc_malloc(sz); if(!data) printf("DATA IS NULL\n"); element_to_bytes(data, elem); fwrite(data, sz, 1, myfile); pbc_free(data); }
void element_to_file(element_t element, char* outputFile){ const int int_bytes_of_element = element_length_in_bytes(element); unsigned char * element_byte_form = (unsigned char *)malloc( int_bytes_of_element * sizeof(unsigned char)); element_to_bytes(element_byte_form, element); element_from_bytes(element, element_byte_form); FILE* fp_element = fopen(outputFile, "w"); fwrite(element_byte_form, 1, int_bytes_of_element, fp_element); fclose( fp_element ); free(element_byte_form); }
//generae a 128bit hash from element // RETURN 33 bytes long char[] // MALLOC : RET !!!!!!! unsigned char* H_2(element_t element) { //convert elemnt to sztring int element_length = element_length_in_bytes(element); unsigned char buff[element_length]; element_to_bytes(buff, element); //hash the string unsigned char* hash = (unsigned char*) malloc(MD5_DIGEST_LENGTH * sizeof( unsigned char)) ; MD5(buff, element_length, hash); return hash ; }
int main(int argc, char ** argv) { pbc_param_t ec_params; pairing_t pairing; unsigned int rbits = 40, qbits = 128; element_t *g1, *g2, *gt; for (int s = 10; s <= 1000; s += 10) { while (qbits <= 4096) { fprintf(stderr, "%d", qbits); pbc_param_init_a_gen(ec_params, rbits, qbits); pairing_init_pbc_param(pairing, ec_params); element_init_G1(g1, pairing); element_init_G2(g2, pairing); element_init_GT(gt, pairing); struct timeval tv1, tv2; int bc = element_length_in_bytes(g1); for (int i = 0; i < 100; i++) { if (0 == i % 10) fprintf(stderr, "."); element_random(g1); element_random(g2); gettimeofday(&tv1, NULL); pairing_apply(gt, g1, g2, pairing); gettimeofday(&tv2, NULL); double time = tv2.tv_sec - tv1.tv_sec; time *= (1000 * 1000); time += tv2.tv_usec - tv1.tv_usec; fprintf(stdout, "%d %d %d %d %d\n", bc, rbits, qbits, i, ((int) time)); } for (int j = 0; j < s; j++) { element_clear(g1[j]); element_clear(g2[j]); element_clear(gt[j]); } rbits *= 2; qbits *= 2; fprintf(stderr, "\n"); } free(g1); free(g2); free(g3); } }
int newepoch_save(char *out,epoch_item_t *ep,setup_params_t * setup) { FILE *fp = NULL; uint32_t elem_size = 0; int rv = 0; unsigned char *buf = NULL; fp=fopen(out,"wb"); if(!fp) { pbgp_error("newepoch_save :: %s\n",strerror(errno)); return -1; } elem_size = element_length_in_bytes(ep->acc->elem); buf = (unsigned char *) malloc(elem_size); if(!buf) { pbgp_error("newepoch_save :: cannot allocate buf\n"); rv = -1; goto out; } element_to_bytes(buf,ep->acc->elem); fwrite(&elem_size,sizeof(uint32_t),1,fp); fwrite(buf,elem_size,1,fp); mpz_out_raw(fp,ep->s_acc); ids_save_fp(fp,ep->epls.act); mpz_out_raw(fp,ep->s_new); ids_save_fp(fp,ep->epls.rvk); mpz_out_raw(fp,ep->s_rvk); out: if(buf) free(buf); fclose(fp); return rv; }
static int fq_length_in_bytes(element_ptr e) { eptr p = e->data; return element_length_in_bytes(p->x) + element_length_in_bytes(p->y); }
static int mulg_length_in_bytes(element_ptr e) { return element_length_in_bytes(e->data); }
FENC_ERROR export_components_to_buffer(uint8* buffer, size_t max_len, size_t *result_len, char* fmt, ...) { FENC_ERROR result = FENC_ERROR_NONE; va_list comp_list; uint8* buf_ptr = buffer; char* fmt_ptr; element_t *elt; fenc_attribute_policy *policy; fenc_attribute_list *attribute_list; size_t i_index=0, tmp_len=0; *result_len = 0; /* Iterate through the variable-length argument list. */ va_start(comp_list, fmt); for(fmt_ptr = fmt; *fmt_ptr != '\0'; fmt_ptr++) { if(*fmt_ptr != '%') { continue; } /* Point buf_ptr to the correct offset, unless the buffer is NULL. */ if (buffer != NULL) { buf_ptr = (uint8*)(buffer + *result_len); } switch(*++fmt_ptr) { case 'E': /* Uncompressed element. */ elt = va_arg(comp_list, element_t*); *result_len += element_length_in_bytes(*elt); if (buffer != NULL && *result_len <= max_len) { element_to_bytes(buf_ptr, *elt); } break; case 'C': /* Compressed element. */ elt = va_arg(comp_list, element_t*); tmp_len = element_length_in_bytes_compressed(*elt); *result_len += tmp_len; if (buffer != NULL && *result_len < max_len) { element_to_bytes_compressed(buf_ptr, *elt); } // printf("len of C = '%zu'\n", *result_len); // printf_buffer_as_hex(buf_ptr, tmp_len); break; case 'P': policy = va_arg(comp_list, fenc_attribute_policy*); result = fenc_attribute_policy_to_string(policy->root, (char *)buf_ptr, (max_len - *result_len)); i_index = strchr((char *) buf_ptr, 0) - (char *) buf_ptr; *result_len += i_index + 1; // printf("policy_root: '%s', strlen: '%d', index: '%d'\n", (char *) buf_ptr, strlen((char *) buf_ptr), i_index); break; case 'A': attribute_list = va_arg(comp_list, fenc_attribute_list*); fenc_attribute_list_to_buffer(attribute_list, buf_ptr, (max_len - *result_len), &i_index); *result_len += i_index + 1; // printf("attribute_list: '%s'\n\tlength: '%zu'\n", (char *)buf_ptr, strlen((char *)buf_ptr)); break; case 's': *result_len += strlen(va_arg(comp_list, char *)) + 1; if (buffer != NULL && *result_len <= max_len) { strcpy((char *)buf_ptr, va_arg(comp_list, char *)); } break; case 'd': *result_len += sizeof(int32); if (buffer != NULL && *result_len < max_len) { EXPORT_INT32(buf_ptr, va_arg(comp_list, int32)); } break; default: /* Unrecognized symbol. */ result = FENC_ERROR_INVALID_INPUT; break; } if (buffer != NULL && *result_len > max_len) { return FENC_ERROR_BUFFER_TOO_SMALL; } }
void bbs_sign(unsigned char *sig, int hashlen, void *hash, bbs_group_public_key_ptr gpk, bbs_group_private_key_ptr gsk) { bbs_sys_param_ptr param = gpk->param; pairing_ptr pairing = param->pairing; field_ptr Fp = pairing->Zr; element_t T1, T2, T3; element_t R1, R2, R3, R4, R5; element_t alpha, beta; element_t c; element_t ralpha, rbeta, rx, rdelta1, rdelta2; element_t z0, z1; element_t e10, et0; unsigned char *writeptr = sig; element_init_G1(T1, pairing); element_init_G1(T2, pairing); element_init_G1(T3, pairing); element_init_G1(R1, pairing); element_init_G1(R2, pairing); element_init_GT(R3, pairing); element_init_G1(R4, pairing); element_init_G1(R5, pairing); element_init(c, Fp); element_init(alpha, Fp); element_random(alpha); element_init(beta, Fp); element_random(beta); //temp variables element_init(z0, Fp); element_init(z1, Fp); element_init_GT(et0, pairing); element_init_G1(e10, pairing); element_init(ralpha, Fp); element_random(ralpha); element_init(rbeta, Fp); element_random(rbeta); element_init(rx, Fp); element_random(rx); element_init(rdelta1, Fp); element_random(rdelta1); element_init(rdelta2, Fp); element_random(rdelta2); element_pow_zn(T1, gpk->u, alpha); element_pow_zn(T2, gpk->v, beta); element_add(z0, alpha, beta); element_pow_zn(T3, gpk->h, z0); element_mul(T3, T3, gsk->A); element_pow_zn(R1, gpk->u, ralpha); element_pow_zn(R2, gpk->v, rbeta); /* * rather than computing e(T3,g2), note that T3 = A h^{alpha+beta}, * use precomputed e(A,g2) and e(h,g2), and use appropriate * exponentiations in GT. */ //pairing_apply(et0, T3, gpk->g2, pairing); /* precomputed */ element_pow_zn(et0, gpk->pr_h_g2, z0); /* NB. here z0 = alpha+beta */ element_mul(et0, et0, gsk->pr_A_g2); //element_pow_zn(R3, et0, rx); // pairing_apply(et0, gpk->h, gpk->w, pairing); /* precomputed */ element_add(z0, ralpha, rbeta); element_neg(z0, z0); //element_pow_zn(et0, gpk->pr_h_w, z0); //element_mul(R3, R3, et0); // pairing_apply(et0, gpk->h, gpk->g2, pairing); /* precomputed */ element_add(z1, rdelta1, rdelta2); element_neg(z1, z1); //element_pow_zn(et0, gpk->pr_h_g2, z1); //element_mul(R3, R3, et0); element_pow3_zn(R3, et0, rx, gpk->pr_h_w, z0, gpk->pr_h_g2, z1); //element_pow_zn(R4, T1, rx); element_neg(z0, rdelta1); //element_pow_zn(e10, gpk->u, z0); //element_mul(R4, R4, e10); element_pow2_zn(R4, T1, rx, gpk->u, z0); //element_pow_zn(R5, T2, rx); element_neg(z0, rdelta2); //element_pow_zn(e10, gpk->v, z0); //element_mul(R5, R5, e10); element_pow2_zn(R5, T2, rx, gpk->v, z0); element_t M; element_init_G1(M, pairing); element_from_hash(M, hash, hashlen); unsigned int hash_input_length = element_length_in_bytes(T1) + element_length_in_bytes(T2) + element_length_in_bytes(T3) + element_length_in_bytes(R1) + element_length_in_bytes(R2) + element_length_in_bytes(R3) + element_length_in_bytes(R4) + element_length_in_bytes(R5) + element_length_in_bytes(M); unsigned char *hash_input = malloc(hash_input_length); hash_input += element_to_bytes(hash_input, T1); hash_input += element_to_bytes(hash_input, T2); hash_input += element_to_bytes(hash_input, T3); hash_input += element_to_bytes(hash_input, R1); hash_input += element_to_bytes(hash_input, R2); hash_input += element_to_bytes(hash_input, R3); hash_input += element_to_bytes(hash_input, R4); hash_input += element_to_bytes(hash_input, R5); hash_input += element_to_bytes(hash_input, M); // Could avoid converting to bytes and from bytes hash_input -= hash_input_length; hash_ctx_t context; unsigned char digest[hash_length]; hash_init(context); hash_update(context, hash_input, hash_input_length); hash_final(digest, context); free(hash_input); element_from_hash(c, digest, sizeof(digest)); element_clear(M); //now the r's represent the values of the s's //no need to allocate yet more variables element_mul(z0, c, alpha); element_add(ralpha, ralpha, z0); element_mul(z0, c, beta); element_add(rbeta, rbeta, z0); element_mul(z1, c, gsk->x); element_add(rx, rx, z1); element_mul(z0, z1, alpha); element_add(rdelta1, rdelta1, z0); element_mul(z0, z1, beta); element_add(rdelta2, rdelta2, z0); writeptr += element_to_bytes(writeptr, T1); writeptr += element_to_bytes(writeptr, T2); writeptr += element_to_bytes(writeptr, T3); writeptr += element_to_bytes(writeptr, c); writeptr += element_to_bytes(writeptr, ralpha); writeptr += element_to_bytes(writeptr, rbeta); writeptr += element_to_bytes(writeptr, rx); writeptr += element_to_bytes(writeptr, rdelta1); writeptr += element_to_bytes(writeptr, rdelta2); #ifdef DEBUG element_printf("T1: %B\n", T1); element_printf("T2: %B\n", T2); element_printf("T3: %B\n", T3); element_printf("R1: %B\n", R1); element_printf("R2: %B\n", R2); element_printf("R3: %B\n", R3); element_printf("R4: %B\n", R4); element_printf("R5: %B\n", R5); element_printf("c: %B\n", c); #endif element_clear(T1); element_clear(T2); element_clear(T3); element_clear(R1); element_clear(R2); element_clear(R3); element_clear(R4); element_clear(R5); element_clear(alpha); element_clear(beta); element_clear(c); element_clear(ralpha); element_clear(rbeta); element_clear(rx); element_clear(rdelta1); element_clear(rdelta2); //clear temp variables element_clear(z0); element_clear(z1); element_clear(e10); element_clear(et0); }
// USER JOIN PHASE 3 - user key generation (Join) int xsgs_user_join_phase3(XSGS_PUBLIC_KEY* gpk, XSGS_USER_CERT* ucert, XSGS_JOIN_PHASE1* jpd1, XSGS_JOIN_PHASE2* jpd2, XSGS_JOIN_PHASE3* jpd3, char* usk_pem_filename) { int ret; pairing_ptr pairing = gpk->pairing; field_ptr Fp = pairing->Zr; element_t B, D, R1, R2, h, g1, gt; // B = e(G1 * C, G2) / e(A, W) = e(G1 * C, G2) * e(A^-1, W) element_init_GT(B, pairing); element_init_G1(g1, pairing); element_init_GT(gt, pairing); element_mul(g1, gpk->G1, jpd1->C); element_pairing(B, g1, gpk->G2); element_invert(g1, jpd2->A); element_pairing(gt, g1, gpk->W); element_mul(B, B, gt); // D = e(A, G2) element_init_GT(D, pairing); element_pairing(D, jpd2->A, gpk->G2); // verifies A e Group1, Checks V element_init(h, Fp); element_from_hash(h, jpd1->U.hash, JOIN_HASH_BITS / 8); element_neg(h, h); // R1 = B^s * T1^h element_init_GT(R1, pairing); element_pow_naf2(R1, B, jpd2->V.s, jpd2->V.T1, h); // R2 = D^s * T2^h element_init_GT(R2, pairing); element_pow_naf2(R2, D, jpd2->V.s, jpd2->V.T2, h); // clear tmp element_clear(g1); element_clear(gt); element_clear(h); // h = H(B, D, T1, T2, R1, R2) DWORD data_len = element_length_in_bytes(B) + element_length_in_bytes(D) + element_length_in_bytes(jpd2->V.T1) + element_length_in_bytes(jpd2->V.T2) + element_length_in_bytes(R1) + element_length_in_bytes(R2); BYTE* data_buf = (BYTE*) malloc(data_len); data_buf += element_to_bytes(data_buf, B); data_buf += element_to_bytes(data_buf, D); data_buf += element_to_bytes(data_buf, jpd2->V.T1); data_buf += element_to_bytes(data_buf, jpd2->V.T2); data_buf += element_to_bytes(data_buf, R1); data_buf += element_to_bytes(data_buf, R2); data_buf -= data_len; BYTE* hash = (BYTE*) malloc(JOIN_HASH_BITS / 8); xsgs_hash(data_buf, data_len * 8, hash, JOIN_HASH_BITS); free(data_buf); element_clear(B); element_clear(D); element_clear(R1); element_clear(R2); // compare hashes ret = memcmp(jpd2->V.hash, hash, JOIN_HASH_BITS / 8); free(hash); if (!ret) { element_init_G1(ucert->A, pairing); element_set(ucert->A, jpd2->A); // S = sign(A) DWORD msg_len = element_length_in_bytes(ucert->A); BYTE* msg = (BYTE*) malloc(msg_len); element_to_bytes(msg, ucert->A); ret = xsgs_rsa_sign(usk_pem_filename, msg, msg_len, &(jpd3->S.sig), &(jpd3->S.len)); free(msg); } // return ( S = (rsa signature length, rsa signature) ) return ret; }
// XSGS USER JOIN - complete offline user join algorithm int xsgs_user_join_offline(XSGS_PUBLIC_KEY* gpk, XSGS_ISSUER_KEY* ik, XSGS_USER_CERT** ucert, XSGS_USER_KEY** uk, XSGS_USER_DB_ENTRY** udbe, char* usk_pem_filename) { element_t z, g11, g12; int ret = 0; *ucert = (XSGS_USER_CERT*) malloc(sizeof(XSGS_USER_CERT)); *uk = (XSGS_USER_KEY*) malloc(sizeof(XSGS_USER_KEY)); *udbe = (XSGS_USER_DB_ENTRY*) malloc(sizeof(XSGS_USER_DB_ENTRY)); element_init(z, gpk->pairing->Zr); element_init(g11, gpk->pairing->G1); element_init(g12, gpk->pairing->G1); // 1. choose x, y e Zp at random element_init((*ucert)->x, gpk->pairing->Zr); element_init((*udbe)->UCert.x, gpk->pairing->Zr); element_init((*uk)->y, gpk->pairing->Zr); element_random((*ucert)->x); element_set((*udbe)->UCert.x, (*ucert)->x); element_random((*uk)->y); // 2. C <- H^y element_init((*udbe)->C, gpk->pairing->G1); element_pow_naf((*udbe)->C, gpk->H, (*uk)->y); // 3. A <- (G1 * C)^{1/(gamma + x)} element_init((*ucert)->A, gpk->pairing->G1); element_init((*udbe)->UCert.A, gpk->pairing->G1); element_add(z, ik->gamma, (*ucert)->x); element_invert(z, z); element_mul((*ucert)->A, gpk->G1, (*udbe)->C); element_pow_naf((*ucert)->A, (*ucert)->A, z); element_set((*udbe)->UCert.A, (*ucert)->A); // 4. S <- sign(A) DWORD msg_len = element_length_in_bytes((*ucert)->A); BYTE* msg = (BYTE*) malloc(msg_len); element_to_bytes(msg, (*ucert)->A); ret = xsgs_rsa_sign(usk_pem_filename, msg, msg_len, &((*udbe)->S.sig), &((*udbe)->S.len)); free(msg); if (!ret) { // 5. check A^(x + gamma) = G1 * H^y element_add(z, ik->gamma, (*ucert)->x); element_pow_naf(g11, (*ucert)->A, z); element_pow_naf(g12, gpk->H, (*uk)->y); element_mul(g12, g12, gpk->G1); ret = element_cmp(g11, g12); } element_clear(z); element_clear(g11); element_clear(g12); return ret; }
int join_save(action_data_t *join) { FILE *fpout = NULL; int rv = 0, i = 0; uint32_t elem_size = 0 ; uint8_t *buf = NULL; char fname[MAX_ENVEL_NAME]; unsigned char *sbuf = NULL; if(!join) { errno = EINVAL; pbgp_error("join_save :: join is null"); return -1; } sprintf(fname,"id-%d.env",join->ibk->id->asnum); fpout = fopen(fname,"wb"); if(!fpout) { pbgp_error("join_datasave :: %s\n",strerror(errno)); return -1; } rv = ibe_keypair_savefp(fpout,join->ibk); if(rv < 0 ) { pbgp_error("join_datasave :: %s\n",strerror(errno)); return -1; } elem_size = element_length_in_bytes(join->witness); fwrite(&elem_size,sizeof(uint32_t),1,fpout); buf = (uint8_t *) malloc(elem_size); if(!buf) { pbgp_error("join_datasave :: %s\n",strerror(errno)); return -1; } element_to_bytes(buf,join->witness); fwrite(buf,elem_size,1,fpout); fwrite(&join->pfixlist->size,sizeof(uint32_t),1,fpout); //write prefix list + signatures for(i = 0; i < join->pfixlist->size; i++) { fwrite(&join->pfixlist->ina[i],sizeof(struct in_addr),1,fpout); fwrite(&join->pfixlist->netmask[i],sizeof(uint8_t),1,fpout); elem_size = ibe_signature_serialize(&sbuf,join->pfixlist->pf_sign[i]); if(elem_size < 0 ) { rv = -1; break; } fwrite(&elem_size,sizeof(uint32_t),1,fpout); fwrite(sbuf,elem_size,1,fpout); free(sbuf); sbuf = NULL; } fwrite(&join->pfixlist->tsca,sizeof(time_t),1,fpout); if(sbuf) free(sbuf); if(buf) free(buf); fclose(fpout); return rv; }
int element_length_in_bytes_x_only(element_ptr e) { point_ptr P = (point_ptr)e->data; return element_length_in_bytes(P->x); }
// USER JOIN PHASE 2 - user key generation (Join) int xsgs_user_join_phase2(XSGS_PUBLIC_KEY* gpk, XSGS_USER_DB_ENTRY* udbe, XSGS_ISSUER_KEY* ik, XSGS_PAILLIER_PUBKEY* ppk, XSGS_JOIN_PHASE1* jpd1, XSGS_JOIN_PHASE2* jpd2) { int ret; pairing_ptr pairing = gpk->pairing; field_ptr Fp = pairing->Zr; mpz_t r1, h; //, t; element_t R1, R2, g1, B, D, zp, gt, hp; mpz_init(h); mpz_from_hash(h, jpd1->U.hash, JOIN_HASH_BITS / 8); // 1. verify C e G1 and check U // R1 = g^s * c^h mod n^2 mpz_init(r1); mpz_powm2(r1, ppk->g, jpd1->U.s, jpd1->U.c, h, ppk->n_squared); // R2 = H^s * C^h element_init_G1(R2, pairing); element_pow_naf2_mpz(R2, gpk->H, jpd1->U.s, jpd1->C, h); mpz_clear(h); // h = H(g, n, c, C, H, R1, R2) DWORD data_len = mpz_length_in_bytes(ppk->g) + mpz_length_in_bytes(ppk->n_squared) + mpz_length_in_bytes(jpd1->U.c) + element_length_in_bytes(jpd1->C) + element_length_in_bytes(gpk->H) + mpz_length_in_bytes(r1) + element_length_in_bytes(R2); BYTE* data_buf = (BYTE*) malloc(data_len); data_buf += mpz_to_bytes(data_buf, ppk->g); data_buf += mpz_to_bytes(data_buf, ppk->n_squared); data_buf += mpz_to_bytes(data_buf, jpd1->U.c); data_buf += element_to_bytes(data_buf, jpd1->C); data_buf += element_to_bytes(data_buf, gpk->H); data_buf += mpz_to_bytes(data_buf, r1); data_buf += element_to_bytes(data_buf, R2); data_buf -= data_len; BYTE* hash = (BYTE*) malloc(JOIN_HASH_BITS / 8); xsgs_hash(data_buf, data_len * 8, hash, JOIN_HASH_BITS); free(data_buf); mpz_clear(r1); element_clear(R2); // compare hashes ret = memcmp(jpd1->U.hash, hash, JOIN_HASH_BITS / 8); free(hash); if (!ret) { element_t r; // initialization element_init(udbe->UCert.x, Fp); element_init_G1(udbe->UCert.A, pairing); element_init_G1(udbe->C, pairing); element_init_G1(jpd2->A, pairing); element_init_G1(g1, pairing); element_init_GT(B, pairing); element_init_GT(gt, pairing); element_init(zp, Fp); // save jpd1->C to ubde->C element_set(udbe->C, jpd1->C); // 2. x eR Zp and element_random(udbe->UCert.x); // A <- (G1 * C)^{1/(gamma + x)} element_add(zp, ik->gamma, udbe->UCert.x); element_invert(zp, zp); element_mul(jpd2->A, gpk->G1, jpd1->C); element_pow_naf(jpd2->A, jpd2->A, zp); element_set(udbe->UCert.A, jpd2->A); // 3. B <- e(G1 * C, G2) / e(A, W) = e(G1 * C, G2) * e(A^-1, W) element_mul(g1, gpk->G1, jpd1->C); element_pairing(B, g1, gpk->G2); element_invert(g1, jpd2->A); element_pairing(gt, g1, gpk->W); element_mul(B, B, gt); element_clear(g1); element_clear(zp); element_clear(gt); // 4. D <- e(A, G2) element_init_GT(D, pairing); element_pairing(D, jpd2->A, gpk->G2); // 5. V <- NIZKPoKDL(B, D) // T1 = B^gamma element_init_GT(jpd2->V.T1, pairing); element_pow_zn(jpd2->V.T1, B, ik->gamma); // T2 = D^gamma element_init_GT(jpd2->V.T2, pairing); element_pow_zn(jpd2->V.T2, D, ik->gamma); // r eR Zp element_init(r, Fp); element_random(r); // R1 = B^r element_init_GT(R1, pairing); element_pow_zn(R1, B, r); // R2 = D^r element_init_GT(R2, pairing); element_pow_zn(R2, D, r); // h = H(B, D, T1, T2, R1, R2) data_len = element_length_in_bytes(B) + element_length_in_bytes(D) + element_length_in_bytes(jpd2->V.T1) + element_length_in_bytes(jpd2->V.T2) + element_length_in_bytes(R1) + element_length_in_bytes(R2); data_buf = (BYTE*) malloc(data_len); data_buf += element_to_bytes(data_buf, B); data_buf += element_to_bytes(data_buf, D); data_buf += element_to_bytes(data_buf, jpd2->V.T1); data_buf += element_to_bytes(data_buf, jpd2->V.T2); data_buf += element_to_bytes(data_buf, R1); data_buf += element_to_bytes(data_buf, R2); data_buf -= data_len; jpd2->V.hash = (BYTE*) malloc(JOIN_HASH_BITS / 8); xsgs_hash(data_buf, data_len * 8, jpd2->V.hash, JOIN_HASH_BITS); element_init(hp, Fp); element_from_hash(hp, jpd1->U.hash, JOIN_HASH_BITS / 8); free(data_buf); element_clear(B); element_clear(D); element_clear(R1); element_clear(R2); // s = r - hash * gamma mod p element_init(jpd2->V.s, Fp); element_mul(jpd2->V.s, hp, ik->gamma); element_add(jpd2->V.s, r, jpd2->V.s); element_clear(r); element_clear(hp); } // return (A, V = (T1, T2, hash, s) ) return ret; }
int element_length_in_bytes_compressed(element_ptr e) { point_ptr P = (point_ptr)e->data; return element_length_in_bytes(P->x) + 1; }
int bbs_verify(unsigned char *sig, int hashlen, void *hash, bbs_group_public_key_t gpk) { bbs_sys_param_ptr param = gpk->param; pairing_ptr pairing = param->pairing; field_ptr Fp = pairing->Zr; element_t T1, T2, T3; element_t R1, R2, R3, R4, R5; element_t c, salpha, sbeta, sx, sdelta1, sdelta2; element_t e10, e20, e21, et0, z0, z1; unsigned char *readptr = sig; element_init_G1(T1, pairing); element_init_G1(T2, pairing); element_init_G1(T3, pairing); element_init_G1(R1, pairing); element_init_G1(R2, pairing); element_init_GT(R3, pairing); element_init_G1(R4, pairing); element_init_G1(R5, pairing); element_init(c, Fp); element_init(salpha, Fp); element_init(sbeta, Fp); element_init(sx, Fp); element_init(sdelta1, Fp); element_init(sdelta2, Fp); element_init_G1(e10, pairing); element_init_G2(e20, pairing); element_init_G2(e21, pairing); element_init_GT(et0, pairing); element_init(z0, Fp); element_init(z1, Fp); readptr += element_from_bytes(T1, readptr); readptr += element_from_bytes(T2, readptr); readptr += element_from_bytes(T3, readptr); readptr += element_from_bytes(c, readptr); readptr += element_from_bytes(salpha, readptr); readptr += element_from_bytes(sbeta, readptr); readptr += element_from_bytes(sx, readptr); readptr += element_from_bytes(sdelta1, readptr); readptr += element_from_bytes(sdelta2, readptr); element_neg(z0, c); //element_pow_zn(R1, gpk->u, salpha); //element_pow_zn(e10, T1, z0); //element_mul(R1, R1, e10); element_pow2_zn(R1, gpk->u, salpha, T1, z0); //element_pow_zn(R2, gpk->v, sbeta); //element_pow_zn(e10, T2, z0); //element_mul(R2, R2, e10); element_pow2_zn(R2, gpk->v, sbeta, T2, z0); element_neg(z0, sdelta1); //element_pow_zn(R4, gpk->u, z0); //element_pow_zn(e10, T1, sx); //element_mul(R4, R4, e10); element_pow2_zn(R4, gpk->u, z0, T1, sx); element_neg(z0, sdelta2); //element_pow_zn(R5, gpk->v, z0); //element_pow_zn(e10, T2, sx); //element_mul(R5, R5, e10); element_pow2_zn(R5, gpk->v, z0, T2, sx); /* * compute R3 more efficiently. use precomputed e(g1,g2)^{-1}, * e(h,g2), and e(h,w). this leaves e(T3,g2)^sx and e(T3,w)^c; * compute these with one pairing as e(T3, g2^sx w^c). */ //element_pow_zn(e20, gpk->g2, sx); //element_pow_zn(e21, gpk->w, c); //element_mul(e20, e20, e21); element_pow2_zn(e20, gpk->g2, sx, gpk->w, c); pairing_apply(R3, T3, e20, pairing); //element_pow_zn(et0, gpk->pr_g1_g2_inv, c); //element_mul(R3, R3, et0); element_add(z0, salpha, sbeta); element_neg(z0, z0); //element_pow_zn(et0, gpk->pr_h_w, z0); //element_mul(R3, R3, et0); element_add(z1, sdelta1, sdelta2); element_neg(z1, z1); //element_pow_zn(et0, gpk->pr_h_g2, z1); element_pow3_zn(et0, gpk->pr_g1_g2_inv, c, gpk->pr_h_w, z0, gpk->pr_h_g2, z1); element_mul(R3, R3, et0); #ifdef DEBUG element_printf("T1: %B\n", T1); element_printf("T2: %B\n", T2); element_printf("T3: %B\n", T3); element_printf("R1: %B\n", R1); element_printf("R2: %B\n", R2); element_printf("R3: %B\n", R3); element_printf("R4: %B\n", R4); element_printf("R5: %B\n", R5); #endif int result = 0; element_t M; element_init_G1(M, pairing); element_from_hash(M, hash, hashlen); unsigned int hash_input_length = element_length_in_bytes(T1) + element_length_in_bytes(T2) + element_length_in_bytes(T3) + element_length_in_bytes(R1) + element_length_in_bytes(R2) + element_length_in_bytes(R3) + element_length_in_bytes(R4) + element_length_in_bytes(R5) + element_length_in_bytes(M); unsigned char *hash_input = malloc(hash_input_length); hash_input += element_to_bytes(hash_input, T1); hash_input += element_to_bytes(hash_input, T2); hash_input += element_to_bytes(hash_input, T3); hash_input += element_to_bytes(hash_input, R1); hash_input += element_to_bytes(hash_input, R2); hash_input += element_to_bytes(hash_input, R3); hash_input += element_to_bytes(hash_input, R4); hash_input += element_to_bytes(hash_input, R5); hash_input += element_to_bytes(hash_input, M); // Could avoid converting to bytes and from bytes hash_input -= hash_input_length; hash_ctx_t context; unsigned char digest[hash_length]; hash_init(context); hash_update(context, hash_input, hash_input_length); hash_final(digest, context); free(hash_input); element_t c1; element_init(c1, Fp); element_from_hash(c1, digest, sizeof(digest)); if (!element_cmp(c, c1)) { result = 1; } element_clear(M); element_clear(c1); element_clear(T1); element_clear(T2); element_clear(T3); element_clear(R1); element_clear(R2); element_clear(R3); element_clear(R4); element_clear(R5); element_clear(c); element_clear(salpha); element_clear(sbeta); element_clear(sx); element_clear(sdelta1); element_clear(sdelta2); element_clear(e10); element_clear(e20); element_clear(e21); element_clear(et0); element_clear(z0); element_clear(z1); return result; }
// USER JOIN PHASE 1 - user key generation (Join) void xsgs_user_join_phase1(XSGS_PUBLIC_KEY* gpk, XSGS_USER_KEY* uk, XSGS_PAILLIER_PUBKEY* ppk, XSGS_JOIN_PHASE1* jpd1) { pairing_ptr pairing = gpk->pairing; field_ptr Fp = pairing->Zr; gmp_randstate_t rnd_state; mpz_t y, r, R1, h; element_t R2; // 1.choose y e Zp at random and element_init(uk->y, Fp); element_random(uk->y); // compute C <- H^y element_init_G1(jpd1->C, pairing); element_pow_naf(jpd1->C, gpk->H, uk->y); // 2. U = (c=ext-commit(y), NIZKPEqDL(c, C, H)) // c = ext-commit(y) = g^y mod n^2 mpz_init(y); mpz_init(jpd1->U.c); element_to_mpz(y, uk->y); mpz_powm(jpd1->U.c, ppk->g, y, ppk->n_squared); // zero-knowledge proof of c, C and H init_rand(rnd_state, PAILLIER_MODULO_BITS / 8 + 1); mpz_init(r); mpz_urandomb(r, rnd_state, PAILLIER_MODULO_BITS); gmp_randclear(rnd_state); // R1 = g^r mod n^2 mpz_init(R1); mpz_powm(R1, ppk->g, r, ppk->n_squared); // R2 = H^r element_init_G1(R2, pairing); element_pow_naf_mpz(R2, gpk->H, r); // h = H(g, n, c, C, H, R1, R2) DWORD data_len = mpz_length_in_bytes(ppk->g) + mpz_length_in_bytes(ppk->n_squared) + //mpz_length_in_bytes(ppk->n) + mpz_length_in_bytes(jpd1->U.c) + element_length_in_bytes(jpd1->C) + element_length_in_bytes(gpk->H) + mpz_length_in_bytes(R1) + element_length_in_bytes(R2); BYTE* data_buf = (BYTE*) malloc(data_len); data_buf += mpz_to_bytes(data_buf, ppk->g); data_buf += mpz_to_bytes(data_buf, ppk->n_squared); //data_buf += mpz_to_bytes(data_buf, ppk->n); data_buf += mpz_to_bytes(data_buf, jpd1->U.c); data_buf += element_to_bytes(data_buf, jpd1->C); data_buf += element_to_bytes(data_buf, gpk->H); data_buf += mpz_to_bytes(data_buf, R1); data_buf += element_to_bytes(data_buf, R2); data_buf -= data_len; jpd1->U.hash = (BYTE*) malloc(JOIN_HASH_BITS / 8); xsgs_hash(data_buf, data_len * 8, jpd1->U.hash, JOIN_HASH_BITS); free(data_buf); mpz_clear(R1); element_clear(R2); // s = r - h * y mpz_init(h); mpz_init(jpd1->U.s); mpz_from_hash(h, jpd1->U.hash, JOIN_HASH_BITS / 8); mpz_mul(jpd1->U.s, h, y); mpz_sub(jpd1->U.s, r, jpd1->U.s); mpz_clear(r); mpz_clear(y); mpz_clear(h); // return ( paillier = (pub, prv), C, U = (c, h, s) ) return; }
int main() { unsigned int _steps = 0, hsize = 0; unsigned char hash[EVP_MAX_MD_SIZE + 1]; store_t *store_setup = pbgp_store_open(NULL); if (!store_setup) return pbgp_fatal("store_setup"); else pbgp_debug("setup open"); store_t *store_epoch = pbgp_store_open(NULL); if (!store_epoch) return pbgp_fatal("store_epoch"); else pbgp_debug("epoch open"); store_t *store_added = pbgp_store_open(NULL); if (!store_added) return pbgp_fatal("store_added"); else pbgp_debug("added open"); store_t *store_revoked = pbgp_store_open(NULL); if (!store_revoked) return pbgp_fatal("store_revoked"); else pbgp_debug("rvk open"); store_t *store_glb_added = pbgp_store_open(NULL); if (!store_glb_added) return pbgp_fatal("store_glb_added"); else pbgp_debug("glb ad open"); store_t *store_glb_revoked = pbgp_store_open(NULL); if (!store_glb_revoked) return pbgp_fatal("store_glb_revoked"); else pbgp_debug("glc rvk open"); /////////////////////////////// JOIN SOME ASNUM (ID) const uint32_t as[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; const char *pfxlist[] = { "123.122.121.1/24,123.122.122.1,123.122.122.1/16", "123.122.121.2/24,123.122.122.2,123.122.122.2/16", "123.122.121.3/24,123.122.122.3,123.122.122.3/16", "123.122.121.4/24,123.122.122.4,123.122.122.4/16", "123.122.121.5/24,123.122.122.5,123.122.122.5/16", "123.122.121.6/24,123.122.122.6,123.122.122.6/16", "123.122.121.7/24,123.122.122.7,123.122.122.7/16", "123.122.121.8/24,123.122.122.8,123.122.122.8/16", "123.122.121.9/24,123.122.122.9,123.122.122.9/16", }; uint32_t i, n = sizeof (as) / sizeof (as[0]); setup_params_t *setup = pbgp_setup_init(n + 1); pbgp_setup_fill(setup); // Save ibe __and__ rsa pubkeys for client (AS) pbgp_setup_save_pubkey(setup, store_setup); // IBE keypair for CA=0 for signing prefix list ibe_keypair_t *ibe_keypair = NULL; pbgp_ibe_keypair_init(setup, &ibe_keypair); pbgp_ibe_keypair_gen(setup, 0, ibe_keypair); for (i = 0; i < n; i++) { char *store_name = pbgp_generate_envelope_storage_name(as[i]); pbgp_debug("openening %s", store_name); // store_cidr_in is __always__ in memory database store_t *store_cidr_in = pbgp_store_open(NULL), *store_cidr_out = pbgp_store_open(store_name); // Parse prefixes and store into cidr_in pbgp_store_parsed_cidr(as[i], pfxlist[i], store_cidr_in); // - creates witness for this asnum (on empty list of added id) // - updates epoch asnum storages (store_added / store_revoked) // - calls join_save and write the envelope to storage (disk) pbgp_action_join(setup, ibe_keypair, as[i], store_cidr_in, store_cidr_out, store_added, store_revoked, store_glb_added, store_glb_revoked ); pbgp_debug("joined %s", store_name); pbgp_store_close(store_cidr_out); pbgp_store_close(store_cidr_in); xfree(store_name); } ////////////// UPDATE EPOCH ACCUMULATOR + GLOBAL ASNUM LIST + EPOCH SIGNATURES // // Saves epoch (calls pbgp_epoch_save) to store // This will update global storages (store_glb_added, store_glb_revoked) // pbgp_epoch_claim_new(setup, store_epoch, store_added, store_revoked, store_glb_added, store_glb_revoked ); /////// SERVER SIDE WORK ENDS HERE /////////////////////////////////////////// // Simulate client: reload setup pubkey (sent to the AS) setup_params_t *client_setup = pbgp_setup_init(n + 1); pbgp_setup_load_pubkey(client_setup, store_setup); pbgp_setup_pairing(client_setup); // For testing purpose we re-load epoch data from storage // in a real use case this will be executed by different parts epoch_t *epoch; pbgp_epoch_init(&epoch, client_setup); // this overwrites values in store_added / store_revoked (with themselves) pbgp_epoch_load(store_epoch, epoch, store_added, store_revoked); /////////////////////////////// START ACTIVE // Witness contained into envelope are outdated because there are new joined entities // in the for loop above (only the latest AS joined should be updated) store_iterator_t *iterator = NULL; store_key_t key = STORE_KEY_INIT; uint32_t asnum = 0; // For each asnum in globally active id for (iterator = pbgp_store_iterator_open(store_glb_added); pbgp_store_iterator_uget_next(iterator, STORE_KEY_SET_DATA(key, ASLIST, asnum), NULL, NULL) == 0; ) { char *store_name = pbgp_generate_envelope_storage_name(asnum); store_t *store_cidr_out = pbgp_store_open(store_name); uint32_t client_asnum; element_t client_witness; unsigned char *client_envelope_signature; size_t client_envelope_signature_size = 0; pbgp_debug("join load id:%d", asnum); // load asnum, witness, signature from envelope for this asnum pbgp_join_load(client_setup, store_cidr_out, &client_asnum, &client_witness, &client_envelope_signature, &client_envelope_signature_size); assert(client_asnum == asnum); // compute serialized = (asnum + witness) to check rsa signature on them unsigned char serialized[sizeof asnum + element_length_in_bytes(client_witness)]; memcpy(serialized, &client_asnum, sizeof client_asnum); element_to_bytes(serialized + sizeof client_asnum, client_witness); // verify envelope signature on serialized(asnum, witness) int ret = pbgp_rsa_verify(client_setup->rsa_evp, serialized, sizeof serialized, client_envelope_signature, client_envelope_signature_size); assert(ret == 1); // update envelope witness with new added / revoked id lists pbgp_witness_update(client_setup, store_added, store_revoked, asnum, client_witness); pbgp_store_put_element(store_cidr_out, STORE_KEY_SET_TYPE(key, JOIN, JOIN_WITNESS), client_witness); // ret = 0 if __not__ revoked (id into accumulator) ret = pbgp_is_revoked(setup, asnum, epoch->accumulator, client_witness); assert(ret == 0); // Loop on every prefix from join data and verify prefix signature store_iterator_t *_iterator = pbgp_store_iterator_open(store_cidr_out); while (1) { store_key_t key = STORE_KEY_INIT; size_t ksize = 0, dsize = 0; // Get [ cidr:asnum -> serialized(prefix + netmask + timestamp) ] int ret = pbgp_store_iterator_uget_next_size(_iterator, &ksize, &dsize); if (ret != 0) { break ; } ksize -= STORE_KEY_METADATA_LENGTH; unsigned char kbuf[ksize]; memset (kbuf, 0, ksize); key.data = kbuf; key.dsize = sizeof (kbuf); unsigned char data[dsize]; memset(data, 0, dsize); ret = pbgp_store_iterator_uget_next(_iterator, &key, data, &dsize); if (ret != 0) { break ; } pbgp_debug("reading join data ns=%d type=%d", key.ns, key.type); if (CIDR == key.ns && MESSAGE == key.type) { store_t *message_store = pbgp_store_open(NULL); // // At this point we have // - data = __signed__ serialized(prefix + netmask + timestamp) // - kbuf = cidr with cidr.index = asnum // cidr_t cidr; assert(sizeof (cidr) == key.dsize); memcpy(&cidr, key.data, key.dsize); if (cidr.index == asnum) { // Put [ asnum -> serialized(prefix + netmask + timestamp) ] into message storage store_key_t mkey = STORE_KEY_INIT; // ******* Messages are signed by ID(RIR=CA) id not by ID(AS) ******************* const uint32_t signer_id = 0; // Store [data = message] to pass it to ibe_vrfy pbgp_store_put(message_store, STORE_KEY_SET_DATA(mkey, IBE, signer_id), data, sizeof (data)); // Get signature for this prefix from join data / envelope size_t ssize = 0; cidr.index = SIGNATURE_INDEX; pbgp_store_uget_size(store_cidr_out, STORE_KEY_SET_DATA(mkey, CIDR, cidr), &ssize); assert(ssize > 0); // Signature is serialized, get the data buffer first unsigned char sbuf[ssize]; // store_cidr_out contains join data = envelope pbgp_store_uget(store_cidr_out, &mkey, sbuf, &ssize); // Let's unserialize ibe signature for this prefix ibe_signature_t *ibe_signature; pbgp_ibe_signature_init(client_setup, &ibe_signature); pbgp_ibe_signature_unserialize(sbuf, ibe_signature); // Finally verify ibe signature for this cidr + timestamp unsigned int verified = pbgp_ibe_verify(client_setup, ibe_signature, message_store); assert(verified == 0); pbgp_ibe_signature_clear(ibe_signature); } pbgp_store_close(message_store); } } pbgp_store_iterator_close(_iterator); // end prefix loop // Cleanup client (AS) data loaded from join envelope // __important__: clear elements __before__ freeing setup (pairing) element_clear(client_witness); pbgp_store_close(store_cidr_out); xfree(client_envelope_signature); xfree(store_name); } pbgp_store_iterator_close(iterator); /////////////////////////////// REVOCATION CHECK // // // Empty epoch added list for (i = 0; i < n; i ++) { pbgp_store_delete(store_added, STORE_KEY_SET_DATA(key, ASLIST, as[i])); } // Revoke some "odd" AS ;-) for (i = 0; i < n; i += 2) { pbgp_action_revoke(as[i], store_added, store_revoked, store_glb_added); } // Update accumulator and global list // this will save epoch data to storage (again) and update store_glb_revoked pbgp_epoch_claim_new(setup, store_epoch, store_added, store_revoked, store_glb_added, store_glb_revoked ); // Reload epoch data pbgp_epoch_clear(epoch); // setup should be client_setup in a real use case pbgp_epoch_init(&epoch, setup); // this overwrites values in store_added / store_revoked (with themselves) pbgp_epoch_load(store_epoch, epoch, store_added, store_revoked); // For each asnum check revocation for (i = 0; i < n; i++) { asnum = as[i]; char *store_name = pbgp_generate_envelope_storage_name(asnum); store_t *store_cidr_out = pbgp_store_open(store_name); uint32_t client_asnum; element_t client_witness; unsigned char *client_envelope_signature; size_t client_envelope_signature_size = 0; // load asnum, witness, signature from envelope for this asnum pbgp_join_load(client_setup, store_cidr_out, &client_asnum, &client_witness, &client_envelope_signature, &client_envelope_signature_size); assert(client_asnum == asnum); // verify epoch signatures on hashed added list memset (hash, 0, sizeof hash); hsize = pbgp_rsa_uhash_list_keys(store_added, hash); int verified = pbgp_rsa_verify(client_setup->rsa_evp, hash, hsize, epoch->signature_added, epoch->signature_added_len); assert(verified == 1); // verify epoch signatures on hashed revoked list memset (hash, 0, sizeof hash); hsize = pbgp_rsa_uhash_list_keys(store_revoked, hash); verified = pbgp_rsa_verify(client_setup->rsa_evp, hash, hsize, epoch->signature_revoked, epoch->signature_revoked_len); assert(verified == 1); // update witness pbgp_witness_update(client_setup, store_added, store_revoked, client_asnum, client_witness); pbgp_store_put_element(store_cidr_out, STORE_KEY_SET_TYPE(key, JOIN, JOIN_WITNESS), client_witness); // verify epoch signatures on accumulator unsigned char accbuf[element_length_in_bytes(epoch->accumulator)]; memset (accbuf, 0, sizeof (accbuf)); hsize = element_to_bytes(accbuf, epoch->accumulator); verified = pbgp_rsa_verify(client_setup->rsa_evp, accbuf, element_length_in_bytes(epoch->accumulator), epoch->signature_accumulator, epoch->signature_accumulator_len); assert(verified == 1); int revoked = pbgp_is_revoked(client_setup, client_asnum, epoch->accumulator, client_witness); if (asnum % 2) { assert(revoked); } else { assert(!revoked); } // Cleanup client (AS) data loaded from join envelope element_clear(client_witness); pbgp_store_close(store_cidr_out); xfree(client_envelope_signature); xfree(store_name); } /////////////////////////////// GLOBAL CLEANUP pbgp_ibe_keypair_clear(ibe_keypair); pbgp_epoch_clear(epoch); pbgp_setup_clear(&client_setup); pbgp_setup_clear(&setup); for (i = 0; i < n; i++) { char *store_name = pbgp_generate_envelope_storage_name(as[i]); unlink(store_name); } pbgp_store_close(store_epoch); pbgp_store_close(store_added); pbgp_store_close(store_revoked); pbgp_store_close(store_glb_added); pbgp_store_close(store_glb_revoked); return EXIT_SUCCESS; }
// x in Z_r, g, h in some group of order r // finds x such that g^x = h void element_dlog_pollard_rho(element_t x, element_t g, element_t h) { // see Blake, Seroussi and Smart // only one snark for this implementation int i, s = 20; field_ptr Zr = x->field, G = g->field; element_t asum; element_t bsum; element_t a[s]; element_t b[s]; element_t m[s]; element_t g0, snark; darray_t hole; int interval = 5; mpz_t counter; int found = 0; mpz_init(counter); element_init(g0, G); element_init(snark, G); element_init(asum, Zr); element_init(bsum, Zr); darray_init(hole); //set up multipliers for (i = 0; i < s; i++) { element_init(a[i], Zr); element_init(b[i], Zr); element_init(m[i], G); element_random(a[i]); element_random(b[i]); element_pow_zn(g0, g, a[i]); element_pow_zn(m[i], h, b[i]); element_mul(m[i], m[i], g0); } element_random(asum); element_random(bsum); element_pow_zn(g0, g, asum); element_pow_zn(snark, h, bsum); element_mul(snark, snark, g0); record(asum, bsum, snark, hole, counter); for (;;) { int len = element_length_in_bytes(snark); unsigned char *buf = pbc_malloc(len); unsigned char hash = 0; element_to_bytes(buf, snark); for (i = 0; i < len; i++) { hash += buf[i]; } i = hash % s; pbc_free(buf); element_mul(snark, snark, m[i]); element_add(asum, asum, a[i]); element_add(bsum, bsum, b[i]); for (i = 0; i < hole->count; i++) { snapshot_ptr ss = hole->item[i]; if (!element_cmp(snark, ss->snark)) { element_sub(bsum, bsum, ss->b); element_sub(asum, ss->a, asum); //answer is x such that x * bsum = asum //complications arise if gcd(bsum, r) > 1 //which can happen if r is not prime if (!mpz_probab_prime_p(Zr->order, 10)) { mpz_t za, zb, zd, zm; mpz_init(za); mpz_init(zb); mpz_init(zd); mpz_init(zm); element_to_mpz(za, asum); element_to_mpz(zb, bsum); mpz_gcd(zd, zb, Zr->order); mpz_divexact(zm, Zr->order, zd); mpz_divexact(zb, zb, zd); //if zd does not divide za there is no solution mpz_divexact(za, za, zd); mpz_invert(zb, zb, zm); mpz_mul(zb, za, zb); mpz_mod(zb, zb, zm); do { element_pow_mpz(g0, g, zb); if (!element_cmp(g0, h)) { element_set_mpz(x, zb); break; } mpz_add(zb, zb, zm); mpz_sub_ui(zd, zd, 1); } while (mpz_sgn(zd)); mpz_clear(zm); mpz_clear(za); mpz_clear(zb); mpz_clear(zd); } else { element_div(x, asum, bsum); } found = 1; break; } } if (found) break; mpz_add_ui(counter, counter, 1); if (mpz_tstbit(counter, interval)) { record(asum, bsum, snark, hole, counter); interval++; } } for (i = 0; i < s; i++) { element_clear(a[i]); element_clear(b[i]); element_clear(m[i]); } element_clear(g0); element_clear(snark); for (i = 0; i < hole->count; i++) { snapshot_ptr ss = hole->item[i]; element_clear(ss->a); element_clear(ss->b); element_clear(ss->snark); pbc_free(ss); } darray_clear(hole); element_clear(asum); element_clear(bsum); mpz_clear(counter); }
static int curve_length_in_bytes(element_ptr x) { point_ptr p = (point_ptr)x->data; return element_length_in_bytes(p->x) + element_length_in_bytes(p->y); }