/* Функция шифрует сообщение m, отдает пару m2[2]{r,e} При m >= p возвращает ошибку */ int eg_send(long long P, long long g, long long key, long long m, long long *m2) { long long k; if(m >= P) return -1; k = Random32() / (P - 2) + 1; m2[0] = PowMod(g, k, P); m2[1] = m * PowMod(key, k, P); return 0; }
int main() { // printf("hello, world"); char result[BUFFER_SIZE]; char remainder[BUFFER_SIZE]; // please make sure the bit length is enough before calculate // especially when you do a large power operation // you can change it by define: BIG_INT_BIT_LEN // the default bit length for BigInt is 1024 // routine test puts(Add("2010", "4", result)); puts(Sub("0", "2014", result)); puts(Mul("2", "43", result)); puts(Div("86", "10", result, remainder)); puts(remainder); puts(Mod("-86", "10", result)); puts(PowMod("7", "80", "86", result)); // BigInt test puts(Sub("233333333333333333333333333333333333333333333333", "33", result)); puts(Mul("2333333333333333333333333333333", "2333333333333333333", result)); puts(Div("2333333333333333333333333333333", "2333333333333333332", result, remainder)); puts(remainder); puts(Pow("8", "86", result)); return 0; }
int BabyStep(int A,int B,int C){ map<int,int> Hash; LL buf=1%C,D=buf,K; int i,d=0,tmp; for(i=0;i<=100;buf=buf*A%C,++i)if(buf==B)return i; while((tmp=GCD(A,C))!=1){ if(B%tmp)return -1; ++d; C/=tmp; B/=tmp; D=D*A/tmp%C; } Hash.clear(); int M=(int)ceil(sqrt((double)C)); for(buf=1%C,i=0;i<=M;buf=buf*A%C,++i)if(Hash.find((int)buf)==Hash.end())Hash[(int)buf]=i; for(i=0,K=PowMod((LL)A,M,C);i<=M;D=D*K%C,++i){ tmp=inval((int)D,B,C); if(tmp>0&&Hash.find(tmp)!=Hash.end())return i*M+Hash[tmp]+d; } return -1; }
// TODO: Add the ability to set a maximum number of iterations inline BigInt FindFactor ( const BigInt& n, Int a, const PollardRhoCtrl& ctrl ) { if( a == 0 || a == -2 ) Output("WARNING: Problematic choice of Pollard rho shift"); BigInt tmp, gcd; BigInt one(1); auto xAdvance = [&]( BigInt& x ) { if( ctrl.numSteps == 1 ) { // TODO: Determine if there is a penalty to x *= x /* tmp = x; tmp *= x; tmp += a; x = tmp; x %= n; */ x *= x; x += a; x %= n; } else { PowMod( x, 2*ctrl.numSteps, n, x ); x += a; x %= n; } }; auto QAdvance = [&]( const BigInt& x, const BigInt& x2, BigInt& Q ) { tmp = x2; tmp -= x; Q *= tmp; Q %= n; }; Int gcdDelay = ctrl.gcdDelay; BigInt xi=ctrl.x0; BigInt x2i(xi); BigInt xiSave=xi, x2iSave=x2i; BigInt Qi(1); Int k=1, i=1; // it is okay for i to overflow since it is just for printing while( true ) { // Advance xi once xAdvance( xi ); // Advance x2i twice xAdvance( x2i ); xAdvance( x2i ); // Advance Qi QAdvance( xi, x2i, Qi ); if( k >= gcdDelay ) { GCD( Qi, n, gcd ); if( gcd > one ) { // NOTE: This was not suggested by Pollard's original paper if( gcd == n ) { if( gcdDelay == 1 ) { RuntimeError("(x) converged before (x mod p) at i=",i); } else { if( ctrl.progress ) Output("Backtracking at i=",i); i = Max( i-(gcdDelay+1), 0 ); gcdDelay = 1; xi = xiSave; x2i = x2iSave; } } else { if( ctrl.progress ) Output("Found factor ",gcd," at i=",i); return gcd; } } // NOTE: This was not suggested by Pollard's original paper k = 0; xiSave = xi; x2iSave = x2i; Qi = 1; } ++k; ++i; } }
/* Функция дешифрует сообщение, принимает пару m2[2]{r,e} Возвращает сообщение m */ long long eg_rec(long long P, long long key, long long *m2) { return m2[1] * PowMod(m2[0], P - 1 - key, P); }
inline ZZmod<ID> operator^(ZZmod<ID> const & a, ZZ const & e) { return PowMod(a.Representative(), e, ZZmod<ID>::Modulus()); }
int main(int argc, const char * argv[]) { if (argc < 5) { printf("Error: Too few arguments. <first_long_number_filename> [ + | - | * | / | % | ^ ] <second_long_number_filename> <result_long_number_filename>\n"); return 0; } if (argc > 7) { printf("Error: Too many arguments. <first_long_number_filename> [ + | - | * | / | % | ^ ] <second_long_number_filename> <result_long_number_filename> <module_long_number_filename> <-b>\n"); return 0; } FILE* firstLongNumFile = fopen(argv[1], "r"); if (!firstLongNumFile) { printf("Error: Unable to open file: %s \n", argv[1]); return 0; } fclose(firstLongNumFile); const char* operation = argv[2]; if ((strlen(operation) > 1 || operation[0] == '\0') || operation[0] != '+' && operation[0] != '-' && operation[0] != '*' && operation[0] != '/' && operation[0] != '%' && operation[0] != '^') { printf("Error: Wrong operation: %s \n", operation); return 0; } FILE* secondLongNumFile = fopen(argv[3], "r"); if (!secondLongNumFile) { printf("Error: Unable to open file: %s \n", argv[3]); return 0; } fclose(secondLongNumFile); FILE* resultLongNumFile = fopen(argv[4], "r"); if (!resultLongNumFile) { printf("Error: Unable to open file: %s \n", argv[4]); return 0; } fclose(resultLongNumFile); ///////////////////////////////// int bin = 0; if (argc == 5) if (argv[2][0] == '^') { printf("Error: Input module file\n"); return 0; } if (argc == 6) { if (argv[2][0] == '^') { FILE* moduleLongNumFile = fopen(argv[5], "r"); if (!moduleLongNumFile) { printf("Error: Unable to open file: %s \n", argv[5]); return 0; } fclose(moduleLongNumFile); } else { if (strcmp(argv[5], "-b")) { printf("Error: Invalid flag: %s \n", argv[5]); return 0; } bin = 1; } } if (argc == 7) { FILE* moduleLongNumFile = fopen(argv[5], "r"); if (!moduleLongNumFile) { printf("Error: Unable to open file: %s \n", argv[5]); return 0; } fclose(moduleLongNumFile); if (strcmp(argv[6], "-b")) { printf("Error: Invalid flag: %s \n", argv[6]); return 0; } bin = 1; } //////////////////////////// LongNumberClass a,b; //upload first large number------------------ if(bin == 1) a.ReadBin(argv[1]); else a.ReadText(argv[1]); //upload second large number------------------------------------------------------------------------------------- if(bin == 1) b.ReadBin(argv[3]); else b.ReadText(argv[3]); //perform chosen operation---------------------------------------------------------------------------------------- LongNumberClass result; switch (operation[0]) { case '+': { result = a + b; break; } case '-': { result = a - b; break; } case '*': { result = a * b; break; } case '/': { result = a / b; break; } case '%': { result = a % b; break; } case '^': { LongNumberClass c; if(bin == 1) c.ReadBin(argv[5]); else c.ReadText(argv[5]); result = PowMod(a, b, c); break; } default: break; } //save result long number--------------- if (bin == 1) result.WriteBin(argv[4]); else result.WriteText(argv[4]); return 0; }
unsigned int RSA32::Decrypt( const unsigned int p_message ) { return PowMod( p_message, m_d, m_n ); }
inline BigInt FindFactor ( const BigInt& n, DynamicSieve<SieveUnsigned>& sieve, const PollardPMinusOneCtrl<SieveUnsigned>& ctrl ) { const double twoLog = Log( 2. ); const double nLog = double( Log( BigFloat(n) ) ); const BigInt zero(0), one(1); // Keep all of the generated primes sieve.SetStorage( true ); SieveUnsigned smooth1 = ctrl.smooth1; SieveUnsigned smooth2 = ctrl.smooth2; SieveUnsigned smooth1Bound = Max( Pow(10ULL,9ULL), 8ULL*smooth1 ); SieveUnsigned smooth2Bound = Max( Pow(10ULL,10ULL), 8ULL*smooth2 ); // Ensure that we do not have a GCD of n appear too many times despite // separately checking the powers of two bool separateOdd=false; Int maxGCDFailures=10; Int numGCDFailures=0; BigInt smallPrime, gcd, tmp, diffPower; while( true ) { // Ensure that we have sieved at least up until smooth1 bool neededStage1Sieving = ( sieve.oddPrimes.back() < smooth1 ); if( ctrl.progress && neededStage1Sieving ) Output ("Updating sieve from ",sieve.oddPrimes.back()," to ",smooth1); sieve.Generate( smooth1 ); if( ctrl.progress && neededStage1Sieving ) Output("Done sieving for stage 1"); // Uniformly select a in (Z/(n))* // (alternatively, we could set a=2) BigInt a = SampleUniform( zero, n ); while( GCD( a, n ) != one ) { a = SampleUniform( zero, n ); } if( !separateOdd ) { // Handle 2 separately unsigned smallPrimeExponent = unsigned(nLog/twoLog); for( Int i=0; i<smallPrimeExponent; ++i ) { // a = a^2 (mod n) a *= a; a %= n; } } auto smooth1End = std::upper_bound ( sieve.oddPrimes.begin(), sieve.oddPrimes.end(), smooth1 ); for( auto iter=sieve.oddPrimes.begin(); iter<smooth1End; ++iter ) { auto smallPrime = *iter; double smallPrimeLog = double(Log(double(smallPrime))); unsigned smallPrimeExponent = unsigned(nLog/smallPrimeLog); for( Int i=0; i<smallPrimeExponent; ++i ) { // a = a^smallPrime (mod n) PowMod( a, smallPrime, n, a ); } } // gcd := GCD( a-1, n ) tmp = a; tmp -= 1; GCD( tmp, n, gcd ); if( gcd > one && gcd < n ) { if( ctrl.progress ) Output("Found stage-1 factor of ",gcd); return gcd; } if( separateOdd ) { unsigned twoExponent = unsigned(nLog/twoLog); for( Int i=0; i<twoExponent; ++i ) { // a = a*a (mod n) a *= a; a %= n; //gcd = GCD( a-1, n ); tmp = a; tmp -= 1; GCD( tmp, n, gcd ); if( gcd > one && gcd < n ) { if( ctrl.progress ) Output("Found separate stage-1 factor of ",gcd); return gcd; } } } if( gcd == n ) { if( separateOdd ) { ++numGCDFailures; if( numGCDFailures >= maxGCDFailures ) RuntimeError ("Too many GCD failures despite separately checking " "powers of two"); } else { ++numGCDFailures; separateOdd = true; if( ctrl.progress ) Output("GCD was n; will separately check powers of two"); } continue; } else // gcd == one { if( ctrl.progress ) Output("Proceeding to stage-2"); } // Run stage-2 // ----------- // Store all powers of a^{d_i}, where d_i is the difference between // primes p_{i+1} and p_i, where smooth1 < p_{i+1} <= smooth2 bool neededStage2Sieving = ( sieve.oddPrimes.back() < smooth2 ); if( ctrl.progress && neededStage2Sieving ) Output ("Updating sieve from ",sieve.oddPrimes.back()," to ",smooth2); sieve.Generate( smooth2 ); if( ctrl.progress && neededStage2Sieving ) Output("Done sieving for stage 2"); // NOTE: stage1End has potentially been invalidated due to reallocation auto stage2Beg = std::lower_bound ( sieve.oddPrimes.begin(), sieve.oddPrimes.end(), smooth1 ); auto stage2End = std::upper_bound ( stage2Beg, sieve.oddPrimes.end(), smooth2 ); std::map<SieveUnsigned,BigInt> diffPowers; for( auto iter=stage2Beg; iter<stage2End; ++iter ) { SieveUnsigned diff = *iter - *(iter-1); auto search = diffPowers.find( diff ); const size_t whichPrime = (iter-sieve.oddPrimes.begin())+1; Output(" ",whichPrime,": ",*iter," - ",*(iter-1)," = ",diff); if( search == diffPowers.end() ) { PowMod( a, diff, n, diffPower ); diffPowers.insert( std::make_pair(diff,diffPower) ); Output(" Stored ",a,"^",diff,"=",diffPower); } else Output(" diff=",diff," was redundant"); } // Test each stage two candidate for( auto iter=stage2Beg; iter<stage2End; ++iter ) { SieveUnsigned diff = *iter - *(iter-1); a *= diffPowers[diff]; a %= n; //gcd = GCD( a-1, n ); tmp = a; tmp -= 1; GCD( tmp, n, gcd ); if( gcd > one && gcd < n ) { if( ctrl.progress ) Output("Found stage-2 factor of ",gcd); return gcd; } } if( gcd == n ) { if( separateOdd ) { if( ctrl.progress ) Output("GCD failure ",numGCDFailures); ++numGCDFailures; if( numGCDFailures >= maxGCDFailures ) RuntimeError ("Too many GCD failures despite separately checking " "powers of two"); } else { ++numGCDFailures; separateOdd = true; if( ctrl.progress ) Output("GCD was n; will separately check powers of two"); } continue; } else // gcd == one { if( smooth1 >= smooth1Bound ) { RuntimeError ("Stage-1 smoothness bound of ",smooth1Bound," exceeded"); } if( smooth2 >= smooth2Bound ) { RuntimeError ("Stage-2 smoothness bound of ",smooth2Bound," exceeded"); } smooth1 *= 2; smooth2 *= 2; if( ctrl.progress ) Output ("Increased stage-1 smoothness to ",smooth1," and stage-2 " "smoothness to ",smooth2); } } }