void primitive_root(int n, int* a) { /** * TERMINATE condition */ if (n <= 2) return; int p = find_closest_prime(n); int l = (p+1)/2; int r = (n+1)/2 - l; /** * Before shift: * |---l---| |--r--| |---l---| |--r--| * ^^^^^^^^^^^^^^^^^ * * After shift: * * |---l---| |---l---| |--r--| |--r--| * ^^^^^^^^^^^^^^^^^ */ shift_right(r+l, a+l, l); primitive_root_prime(l+l, a); primitive_root(r+r, a+l+l); }
INT finite_field_domain_primitive_root() { domain *d; INT q; if (!is_finite_field_domain(d)) { cout << "finite_field_domain_primitive_root() no finite field domain" << endl; exit(1); } q = finite_field_domain_order_int(d); if (is_GFp_domain(d)) { return primitive_root(q, FALSE /* f_v */); } else { integer a; INT i, o; cout << "finite_field_domain_primitive_root():" << endl; for (i = 1; i < q; i++) { a.m_i(i); o = a.order(); cout << "order of " << i << " is " << o << endl; if (o == q - 1) { return i; } } cout << "finite_field_domain_primitive_root() couldn't find primitive root!" << endl; exit(1); // INT p, f; // factor_prime_power(q, &p, &f); // return p; } }
vector <int> residue(int p,int N,int a) { int g=primitive_root(p); long long m=discrete_log(g,a,p); vector<int> ret; if (a==0) { ret.push_back(0); return ret; } if (m==-1) return ret; long long A=N,B=p-1,C=m,x,y; long long d=extended_gcd(A,B,x,y); if (c%d!=0) return ret; x=x*(C/d)%B; long long delta=B/d; for (int i=0;i<d;i++) { x=((x+delta)%B+B)%B; ret.push_back((int)pow_mod(g,x,p)); } sort(ret.begin(),ret.end()); ret.erase(unqinue(ret.begin(),ret.end()),ret.end()); return ret; }
void unipoly::Singer(INT p, INT f, INT f_v, INT f_vv) { INT m, i, a, b, low, high; Vector vp, ve; unipoly x; if (p <= 1) { cout << "unipoly::Singer(): p <= 1\n"; exit(1); } if (!is_prime(p)) { cout << "unipoly::Singer(): p not prime\n"; exit(1); } m = ::i_power_j(p, f) - 1; factor_integer(m, vp, ve); a = primitive_root(p, f_v); for (b = 0; b < p; b++) { x.singer_candidate(p, f, b, a); if (f_v) { cout << "singer candidate " << x << endl; } if (x.is_irreducible_GFp(p, f_vv) && x.is_primitive(m, p, vp, f_vv)) { if (f_v) { cout << "OK" << endl; } swap(x); return; } } low = m + 1; high = low << 1; for (i = low; i <= high; i++) { x.numeric_polynomial(i, p); if (f_v) { cout << "candidate " << i - low + 1 << " : " << x << endl; } if (x.is_irreducible_GFp(p, f_vv) && x.is_primitive(m, p, vp, f_vv)) { if (f_v) { cout << "OK" << endl; } swap(x); return; } } cout << "ERROR: did not find an irrducible primitive polynomial, help!\n"; exit(1); }
//KEY GENERATION ALGORITHM IN DIFFIE-HELLMAN KEY EXCHANGE PROTOCOL void KeyGeneration(long int *q, long int *alpha, long int *private_key, long int *public_key) { long int p; if(print_flag1) printf("\n selecting q->\n\r"); while(1) { srand((unsigned int) time(NULL)); p = random() % LARGE; if( p <= 10000) continue; /* test for even number */ if ( (p & 0x01) == 0 ) continue; /* Trivial divisibility test by primes 3, 5, 7, 11, 13, 17, 19 */ if ( (p % 3 == 0 ) || (p % 5 == 0) || (p % 7 == 0) || (p % 11 == 0 ) || (p % 13 == 0) || ( p % 17 == 0) || ( p% 19 == 0) ) continue; if( MillerRobinTest(p, MAX_ITERATION) ) break; } *q = p; if (verify_prime(p) ) printf( "q = %ld is prime\n", *q); else { printf("q = %ld is composite\n", *q); exit(0); } /* Select a primitive root of q */ *alpha = primitive_root( p ); /* Select a private key < q randomly */ *private_key = rand() % p; /* Compute the public key */ *public_key = ModPower(*alpha, *private_key, *q); }
int primitive_root(int m, prime_holder& prim) { int phi = euler_phi(prim.factor_integer(m)); auto phi_factors = prime_factors(prim.factor_integer(phi)); return primitive_root(m, phi, phi_factors); }
int main(int argc, char*argv[]) { // transform size (must be prime) unsigned int nfft = 17; int dopt; while ((dopt = getopt(argc,argv,"uhn:")) != EOF) { switch (dopt) { case 'h': usage(); return 0; case 'n': nfft = atoi(optarg); break; default: exit(1); } } // validate input if ( nfft <= 2 || !is_prime(nfft)) { fprintf(stderr,"error: %s, input transform size must be prime and greater than two\n", argv[0]); exit(1); } unsigned int i; // create and initialize data arrays float complex * x = (float complex *) malloc(nfft * sizeof(float complex)); float complex * y = (float complex *) malloc(nfft * sizeof(float complex)); float complex * y_test = (float complex *) malloc(nfft * sizeof(float complex)); if (x == NULL || y == NULL || y_test == NULL) { fprintf(stderr,"error: %s, not enough memory for allocation\n", argv[0]); exit(1); } for (i=0; i<nfft; i++) { //x[i] = randnf() + _Complex_I*randnf(); x[i] = (float)i + _Complex_I*(3 - (float)i); y[i] = 0.0f; } // compute output for testing dft_run(nfft, x, y_test, DFT_FORWARD, 0); // // run Rader's algorithm // // compute primitive root of nfft unsigned int g = primitive_root(nfft); // create and initialize sequence unsigned int * s = (unsigned int *)malloc((nfft-1)*sizeof(unsigned int)); for (i=0; i<nfft-1; i++) s[i] = modpow(g, i+1, nfft); #if DEBUG printf("computed primitive root of %u as %u\n", nfft, g); // generate sequence (sanity check) printf("s = ["); for (i=0; i<nfft-1; i++) printf("%4u", s[i]); printf("]\n"); #endif // compute DFT of sequence { exp(-j*2*pi*g^i/nfft }, size: nfft-1 // NOTE: R[0] = -1, |R[k]| = sqrt(nfft) for k != 0 // NOTE: R can be pre-computed float complex * r = (float complex*)malloc((nfft-1)*sizeof(float complex)); float complex * R = (float complex*)malloc((nfft-1)*sizeof(float complex)); for (i=0; i<nfft-1; i++) r[i] = cexpf(-_Complex_I*2*M_PI*s[i]/(float)(nfft)); dft_run(nfft-1, r, R, DFT_FORWARD, 0); // compute DFT of permuted sequence, size: nfft-1 float complex * xp = (float complex*)malloc((nfft-1)*sizeof(float complex)); float complex * Xp = (float complex*)malloc((nfft-1)*sizeof(float complex)); for (i=0; i<nfft-1; i++) { // reverse sequence unsigned int k = s[nfft-1-i-1]; xp[i] = x[k]; } dft_run(nfft-1, xp, Xp, DFT_FORWARD, 0); // compute inverse FFT of product for (i=0; i<nfft-1; i++) Xp[i] *= R[i]; dft_run(nfft-1, Xp, xp, DFT_REVERSE, 0); // set DC value y[0] = 0.0f; for (i=0; i<nfft; i++) y[0] += x[i]; // reverse permute result, scale, and add offset x[0] for (i=0; i<nfft-1; i++) { unsigned int k = s[i]; y[k] = xp[i] / (float)(nfft-1) + x[0]; } // free internal memory free(r); free(R); free(xp); free(Xp); free(s); // // print results // for (i=0; i<nfft; i++) { printf(" y[%3u] = %12.6f + j*%12.6f (expected %12.6f + j%12.6f)\n", i, crealf(y[i]), cimagf(y[i]), crealf(y_test[i]), cimagf(y_test[i])); } // compute error float rmse = 0.0f; for (i=0; i<nfft; i++) { float e = cabsf(y[i] - y_test[i]); rmse += e*e; } rmse = sqrtf(rmse / (float)nfft); printf("RMS error : %12.4e (%s)\n", rmse, rmse < 1e-3 ? "pass" : "FAIL"); // free allocated memory free(x); free(y); free(y_test); return 0; }