// // randomph.cpp // randomph // // Created by Paul Beale on 11/7/14. // Copyright (c) 2014 Paul Beale. All rights reserved. // #include "randomph.h" #include #include #include #include #include #include using namespace std; // 32-bit pseudorandom number generator based on // Pohlig-Hellman encryption of integer messages with pseudorandom skips // n: safe prime prime in [2^31..2^32], i.e. (n-1)/2 is also prime // m: message with 0<=m0 && y==1) return 0; //not prime y=(y*y)%n; //y=multiplymod(y,y,n); } if (ok==0) return 0; // not prime } return 1; //prime } // tests to see if n is a safe prime for n<2^32, 1 if safe prime, 0 if not // a safe prime is a prime n such that (n-1)/2 is also prime // 1 if safeprime, 0 otherwise int safeprimeq(unsigned long n) { unsigned long n12; if(n%2==0) return 0; if (n < 84) { if (n==5) return 1; if (n==7) return 1; if (n==11) return 1; if (n==23) return 1; if (n==47) return 1; if (n==59) return 1; if (n==83) return 1; return 0; } n12=(n-1)/2; unsigned long prime[12]={2,3,5,7,11,13,17,19,23,29,31,37}; for (int i=0;i<12;i++) if (n%prime[i]==0 || n12%prime[i]==0) return 0; if (primeq(n)==0) return 0; if (primeq(n12)==0) return 0; return 1; } // selects the next prime above n if offset = +1, jth prime above n if offset = +j // selects the next prime below n if offset = -1, jth prime below n if offset = -j unsigned long nextprime(unsigned long n, long offset) { int updown,nprimes,pq; if (offset == 0) return 0; if (offset > 0) updown=+1; else updown=-1; //offset=abs(offset); if (offset < 0) offset = -offset; nprimes=0; do { n += updown; if (n<2) return 0; pq=primeq(n); if (pq) nprimes++; } while (!pq || nprimes < offset); return n; } // selects the next safe prime above n if offset = +1, // jth safe prime above n if offset = +j // selects the next safe prime below n if offset = -1, // jth safe prime below n if offset = -j unsigned long nextsafeprime(unsigned long n, long offset) { int updown,nprimes,pq; if (offset == 0) return 0; if (offset > 0) updown=+1; else updown=-1; //offset=abs(offset); if (offset < 0) offset = -offset; nprimes=0; do { n += updown; if ( n < 2) return 0; pq=safeprimeq(n); if (pq) nprimes++; } while (!pq || nprimes < offset); return n; } //returns one of 3060794 safe primes between 2^31 and 2^32 starting near 2^32 // with 0 <= i < 3060794 // safeprime(0) = 4294967087 is the largest safe prime below 2^32 // safeprime(3060793) = 2147483783 is the smallest safe prime above 2^31 unsigned long safeprime(long i) { unsigned long safeprimes[31]={4294967087, 4222725707, 4150883063, 4079008547, 4006857719, 3935091059, 3863505827, 3792054359, 3720601559, 3649365899, 3578380259, 3507339959, 3436690847, 3366364187, 3295757987, 3225327167, 3155044799, 3085122659, 3015377447, 2945577263, 2876115563, 2806385207, 2736992087, 2667700019, 2598759287, 2530175939, 2461716743, 2393244167, 2324812307, 2256486719, 2188727483}; if (i<0) return 0; if (i>=3060794) return 0; unsigned long n=safeprimes[i/100000]; int j=i%100000; if (j > 0) n=nextsafeprime(n, -j); return n; }