/* * gen_priv_key() */ void gen_priv_key(const unsigned int seed) { uint1024 a,one; int i; if (verbose>1) puts(" Generating items"); srandom(seed); uint_to_1024(priv_sum,0); for (i=0; i<ITEMS; i++) { uint_to_1024(private_key[i],0); while (cmp1024(private_key[i],priv_sum)<=0) { shl1024(private_key[i],4); uint_to_1024(a,(uint) (16.0*random()/RAND_MAX)); add1024(private_key[i],a); } add1024(priv_sum,private_key[i]); } if (verbose>1) puts(" Counting 'm'"); find_m(); if (verbose>1) puts(" Counting 'v'"); find_v(); if (verbose>1) puts(" Counting 'u'"); find_u(); if (verbose>1) puts(" Checking u*v=1 (mod m)"); cpy1024(a, u); mul1024modN(a,v,m); uint_to_1024(one,1); if (cmp1024(one,a)) { puts("!! WARNING !! u*v != 1 (mod m) !! WARNING !!"); puts("This key will provide only one-way trip !"); if (verbose>1) puts("E.g. it's usable only for encryption, not decryption !"); } }
int main() { PFC pfc(AES_SECURITY); // initialise pairing-friendly curve miracl *mip=get_mip(); // get handle on mip (Miracl Instance Pointer) time_t seed; int i,j,k,l,n,m,d,nS; Big **LSSS; int *attr; Big det,order=pfc.order(); // get pairing-friendly group order Big alpha,a,M,CT,s,t; G2 g2,g2a,*h,CD; G1 g1,g1a,K,L,MSK; GT eg2g1a,mask; time(&seed); // initialise (insecure!) random numbers irand((long)seed); // Setup pfc.random(alpha); pfc.random(a); pfc.random(g1); pfc.random(g2); pfc.precomp_for_mult(g1); // g1 is fixed, so precompute on it pfc.precomp_for_mult(g2); // g2 is fixed, so precompute on it eg2g1a=pfc.power(pfc.pairing(g2,g1),alpha); pfc.precomp_for_power(eg2g1a); g1a=pfc.mult(g1,a); g2a=pfc.mult(g2,a); pfc.precomp_for_mult(g2a); // g2a is fixed, so precompute on it h=new G2[U]; for (i=0;i<U;i++) { pfc.random(h[i]); pfc.precomp_for_mult(h[i]); // precompute on h[.] } MSK=pfc.mult(g1,alpha); // Encrypt m=find_m(Access); d=find_d(Access); LSSS=new Big *[m]; for (i=0;i<m;i++) LSSS[i]=new Big[d+1]; // get memory for each row attr=new int [m]; make_LSSS(Access,m,d,LSSS,attr); // create LSSS matrix from Access structure cout << "LSSS matrix " << m << "x" << d << endl; for (i=0;i<m;i++) { for (j=0;j<d;j++) cout << LSSS[i][j] << " "; cout << " " << (char)attr[i] << endl; } cout << endl; mip->IOBASE=256; M=(char *)"test message"; cout << "Message to be encrypted= " << M << endl; mip->IOBASE=16; Big *v=new Big [d]; Big *lambda=new Big [m]; Big *r=new Big [m]; for (i=0;i<d;i++) pfc.random(v[i]); s=v[0]; for (i=0;i<m;i++) pfc.random(r[i]); G2 *C=new G2 [m]; G1 *D=new G1 [m]; for (i=0;i<m;i++) { lambda[i]=0; for (j=0;j<d;j++) lambda[i]+=modmult(LSSS[i][j],v[j],order); lambda[i]%=order; } CT=lxor(M,pfc.hash_to_aes_key(pfc.power(eg2g1a,s))); CD=pfc.mult(g2,s); for (i=0;i<m;i++) { C[i]=pfc.mult(g2a,lambda[i])+pfc.mult(h[attr[i]-'A'],-r[i]); D[i]=pfc.mult(g1,r[i]); } // keygen cout << "Generating keys" << endl; pfc.random(t); K=MSK+pfc.mult(g1a,t); L=pfc.mult(g1,t); G2 *KX=new G2[U]; nS=0; while (auth[nS]!=0) { j=auth[nS++]-'A'; KX[j]=pfc.mult(h[j],t); pfc.precomp_for_pairing(KX[j]); } // decrypt - and apply some optimisations e.g. e(A,B)*e(A,C) = e(A,B+C) cout << "Decrypting" << endl; int *rows=new int [m]; Big *w=new Big [m]; if (!reduce_LSSS(order,m,d,LSSS,attr,auth,rows,w)) { cout << "Unable to decrypt - insufficient attributes" << endl; exit(0); } cout << "reduced matrix= " << m << "x" << d << endl; // Note that w[i] are usually very small, so this is fast G2 TC; for (i=0;i<m;i++) { cout << "w[i]= " << w[i] << endl; TC=TC+pfc.mult(C[rows[i]],w[i]); D[rows[i]]=pfc.mult(D[rows[i]],-w[i]); } TC=-TC; // combine rows which share same attribute for (i=0;i<m;i++) { k=rows[i]; for (j=i+1;j<m;j++) { if (attr[j]==attr[i]) { D[k]=D[k]+D[rows[j]]; // combine them for (n=j;n<m;n++) { rows[n]=rows[n+1]; attr[n]=attr[n+1]; } m--; // delete row } } } G2 **t2=new G2* [m+2]; G1 **t1=new G1* [m+2]; t2[0]=&CD; t1[0]=&K; // e(CD,K) t2[1]=&TC; t1[1]=&L; // e(TC,L) for (i=0;i<m;i++) { t2[i+2]=&KX[attr[i]-'A']; t1[i+2]=&D[rows[i]]; } mask=pfc.multi_pairing(m+2,t2,t1); // most pairings benefit from precomputation M=lxor(CT,pfc.hash_to_aes_key(mask)); mip->IOBASE=256; cout << "Decrypted message= " << M << endl; return 0; }