int find_d(int u, int f, int s) { sz[u] = 1; int mx = 0; for (int i = head[i]; i != -1; i = next[i]) { int v = to[i]; if (v != f && !ban[v]) { find_d(v, u, s); sz[u] += sz[v]; mx = max(mx, sz[v]); } } mx = max(mx, s - mx); if (mx < rmx) rmx = mx, d = u; }
int main(int argc, char ** argv) { long long max_n, max_d; long long d; if(argc < 3) printf("Usage: %s max_n=%Ld max_d=%Ld\n", argv[0], max_n = 15499, max_d = 94744); else max_n = atoi(argv[1]), max_d = atoi(argv[2]); printf("%Ld\n", find_d(max_n, max_d)); return 0; }
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; }