long long modPow(int p, int q) { if (q == 0) { return 1; } else if (q == 1) { return p; } long long ret = modPow(p, q/2); return ret * ret % MOD * modPow(p, q % 2) % MOD; }
void SecretShare::modInv(mpz_t result, mpz_t value){ mpz_t temp; mpz_init(temp); mpz_sub_ui(temp, fieldSize, 2); modPow(result, value, temp); mpz_clear(temp); }
void solve() { int n, k; scanf("%d%d", &n, &k); int all = modPow(k, n); int ans = mul(mul(all, (all + MOD - 1) % MOD), (all + MOD - 2) % MOD); ans = mul(mul(mul(ans, n), n), n); printf("%d\n", ans); }
void SecretShare::modSqrt(mpz_t result, mpz_t x){ mpz_t temp; mpz_init(temp); mpz_add_ui(temp, fieldSize, 1); mpz_div_ui(temp, temp, 4); modPow(result, x, temp); mpz_clear(temp); }
void SecretShare::modSqrt(mpz_t* result, mpz_t* x, int size){ mpz_t* power = (mpz_t*)malloc(sizeof(mpz_t) * size); for(int i = 0; i < size; i++){ mpz_init(power[i]); mpz_add_ui(power[i], fieldSize, 1); mpz_div_ui(power[i], power[i], 4); } modPow(result, x, power, size); for(int i = 0; i < size; i++) mpz_clear(power[i]); }
long long combination(int n, int k) { long long upper = 1; for (int i = n; i > n - k; --i) { upper = upper * i % MOD; } long long lower = 1; for (int i = 1; i <= k; ++i) { lower = lower * i % MOD; } return upper * modPow(lower, MOD - 2) % MOD; }
// Pre-condition: base^2 < 2^31, n < sqrt(2^31), 0 <= exp < 2^31. // Post-condition: base raised to the power exp mod n is returned. int modPow(int base, int exp, int n) { // Just in case we are passed in a base that is too big. base = base%n; // Everything raised to the 0 power is 1. if (exp == 0) return 1; // Anything raised to the 1st power is itself. else if (exp == 1) return base; // Utlize the even powered exponent and the rules of exponentiation. else if (exp%2 == 0) return modPow(base*base%n, exp/2, n); // If we can't, then just use our regular solution. else return base*modPow(base, exp-1, n)%n; }
int main() { // Very basic, NOT comprensive, tests of the recursive methods. int vals[4]; printf("7! = %d\n", fact(7)); printf("31^2 + 32^2 + ... + 200^2 = %d\n", sumsq(31, 200)); vals[0] = 37; vals[1] = 48; vals[2] = 56; vals[3] = 63; printf("vals has %d Odd values.\n", ArrayOdd(vals, 4)); print_reverse("writethisbackwards", 18); printf("\n"); printf("3^10 = %d\n", powerA(3,10)); printf("3^11 = %d\n", powerB(3,11)); if (Rbinary(33, vals, 0, 3) == -1) printf("33 was not found in vals.\n"); dectobin(179); printf("\n"); if (check("madamimadam", 11)) printf("madamimadam is a palindrome.\n"); printf("The 27th Fibonacci number is %d\n", fibonacci(27)); // Test of fast exponentiation vs. regular version int start = time(0); int ans1 = slowModPow(6874, 1000000000, 13713); int end1 = time(0); int ans2 = modPow(6874, 1000000000, 13713); int end2 = time(0); printf("ans1 = %d, ans2 = %d.\n", ans1, ans2); printf("slowModExp took %d sec.\n", end1-start); printf("modPow took %d sec.\n", end2-end1); system("PAUSE"); return 0; }
void SecretShare::computeSharingMatrix(){ // initialize the shairngMatrix mpz_t t1, t2; mpz_init(t1); mpz_init(t2); sharingMatrix = (mpz_t**)malloc(sizeof(mpz_t*) * peers); for(int i = 0; i < peers; i++) sharingMatrix[i] = (mpz_t*)malloc(sizeof(mpz_t) * peers); for(int i = 0; i < peers; i++) for(int j = 0; j < peers; j++) mpz_init(sharingMatrix[i][j]); for(int i = 0; i < peers; i++){ for(int j = 0; j < 2*threshold+1; j++){ mpz_set_ui(t1,i+1); mpz_set_ui(t2,j); modPow(sharingMatrix[i][j], t1, t2); } } mpz_clear(t1); mpz_clear(t2); }
void GaussianFactorization(void) { BigInteger prime, q, r, M1, M2, Tmp; struct sFactors *pstFactor; BigIntMultiply(&ReValue, &ReValue, &tofactor); BigIntMultiply(&ImValue, &ImValue, &Tmp); BigIntAdd(&tofactor, &Tmp, &tofactor); NbrFactorsNorm = 0; #ifdef __EMSCRIPTEN__ originalTenthSecond = tenths(); #endif if (tofactor.nbrLimbs == 1 && tofactor.limbs[0].x == 0) { // Norm is zero. w("<ul><li>Any gaussian prime divides this number</li></ul>"); return; } w("<ul>"); if (tofactor.nbrLimbs > 1 || tofactor.limbs[0].x > 1) { // norm greater than 1. Factor norm. int index, index2; char *ptrFactorDec = tofactorDec; NumberLength = tofactor.nbrLimbs; CompressBigInteger(nbrToFactor, &tofactor); strcpy(ptrFactorDec, "Re² + Im² = "); ptrFactorDec += strlen(ptrFactorDec); Bin2Dec(ReValue.limbs, ptrFactorDec, ReValue.nbrLimbs, groupLen); ptrFactorDec += strlen(ptrFactorDec); strcpy(ptrFactorDec, "² + "); ptrFactorDec += strlen(ptrFactorDec); Bin2Dec(ImValue.limbs, ptrFactorDec, ImValue.nbrLimbs, groupLen); ptrFactorDec += strlen(ptrFactorDec); strcpy(ptrFactorDec, "²"); ptrFactorDec += strlen(ptrFactorDec); factor(&tofactor, nbrToFactor, factorsNorm, astFactorsNorm, NULL); NbrFactorsNorm = astFactorsNorm[0].multiplicity; pstFactor = &astFactorsNorm[1]; for (index = 0; index < NbrFactorsNorm; index++) { int *ptrPrime = pstFactor->ptrFactor; NumberLength = *ptrPrime; UncompressBigInteger(ptrPrime, &prime); prime.sign = SIGN_POSITIVE; if (prime.nbrLimbs == 1 && prime.limbs[0].x == 2) { // Prime factor is 2. for (index2 = 0; index2 < pstFactor->multiplicity; index2++) { M1.nbrLimbs = M2.nbrLimbs = 1; M1.limbs[0].x = M2.limbs[0].x = 1; M1.sign = SIGN_POSITIVE; M2.sign = SIGN_NEGATIVE; DivideGaussian(&M1, &M1); // Divide by 1+i DivideGaussian(&M1, &M2); // Divide by 1-i } } if ((prime.limbs[0].x & 2) == 0) { // Prime is congruent to 1 (mod 4) CopyBigInt(&q, &prime); NumberLength = prime.nbrLimbs; memcpy(&TestNbr, prime.limbs, NumberLength * sizeof(limb)); TestNbr[NumberLength].x = 0; GetMontgomeryParms(NumberLength); subtractdivide(&q, 1, 4); // q = (prime-1)/4 memset(&K, 0, NumberLength * sizeof(limb)); memset(minusOneMont, 0, NumberLength * sizeof(limb)); SubtBigNbrModN(minusOneMont, MontgomeryMultR1, minusOneMont, TestNbr, NumberLength); K[0].x = 1; do { // Loop that finds mult1 = sqrt(-1) mod prime in Montgomery notation. K[0].x++; modPow(K, q.limbs, q.nbrLimbs, mult1.limbs); } while (!memcmp(mult1.limbs, MontgomeryMultR1, NumberLength * sizeof(limb)) || !memcmp(mult1.limbs, minusOneMont, NumberLength * sizeof(limb))); K[0].x = 1; modmult(mult1.limbs, K, mult1.limbs); // Convert mult1 to standard notation. UncompressLimbsBigInteger(mult1.limbs, &mult1); // Convert to Big Integer. mult2.nbrLimbs = 1; // mult2 <- 1 mult2.limbs[0].x = 1; mult2.sign = SIGN_POSITIVE; for (;;) { // norm <- (mult1^2 + mult2^2) / prime BigIntMultiply(&mult1, &mult1, &tofactor); BigIntMultiply(&mult2, &mult2, &Tmp); BigIntAdd(&tofactor, &Tmp, &Tmp); BigIntDivide(&Tmp, &prime, &tofactor); if (tofactor.nbrLimbs == 1 && tofactor.limbs[0].x == 1) { // norm equals 1. break; } BigIntRemainder(&mult1, &tofactor, &M1); BigIntRemainder(&mult2, &tofactor, &M2); BigIntAdd(&M1, &M1, &Tmp); BigIntSubt(&tofactor, &Tmp, &Tmp); if (Tmp.sign == SIGN_NEGATIVE) { BigIntSubt(&M1, &tofactor, &M1); } BigIntAdd(&M2, &M2, &Tmp); BigIntSubt(&tofactor, &Tmp, &Tmp); if (Tmp.sign == SIGN_NEGATIVE) { BigIntSubt(&M2, &tofactor, &M2); } // Compute q <- (mult1*M1 + mult2*M2) / norm BigIntMultiply(&mult1, &M1, &q); BigIntMultiply(&mult2, &M2, &Tmp); BigIntAdd(&q, &Tmp, &Tmp); BigIntDivide(&Tmp, &tofactor, &q); // Compute Mult2 <- (mult1*M2 - mult2*M1) / tofactor BigIntMultiply(&mult1, &M2, &r); BigIntMultiply(&mult2, &M1, &Tmp); BigIntSubt(&r, &Tmp, &Tmp); BigIntDivide(&Tmp, &tofactor, &mult2); CopyBigInt(&mult1, &q); mult1.sign = SIGN_POSITIVE; // mult1 <- abs(mult1) mult2.sign = SIGN_POSITIVE; // mult2 <- abs(mult2) } /* end while */ CopyBigInt(&M1, &mult1); CopyBigInt(&M2, &mult2); BigIntSubt(&M1, &M2, &Tmp); if (Tmp.sign == SIGN_NEGATIVE) { CopyBigInt(&Tmp, &mult1); CopyBigInt(&mult1, &mult2); CopyBigInt(&mult2, &Tmp); } for (index2 = 0; index2 < pstFactor->multiplicity; index2++) { DivideGaussian(&mult1, &mult2); BigIntNegate(&mult2, &Tmp); DivideGaussian(&mult1, &Tmp); } } // end p = 1 (mod 4) else { // if p = 3 (mod 4) q.nbrLimbs = 1; // q <- 0 q.limbs[0].x = 0; q.sign = SIGN_POSITIVE; for (index2 = 0; index2 < pstFactor->multiplicity; index2++) { DivideGaussian(&prime, &q); } // end p = 3 (mod 4) } pstFactor++; } } // Process units: 1, -1, i, -i. if (ReValue.nbrLimbs == 1 && ReValue.limbs[0].x == 1) { if (ReValue.sign == SIGN_POSITIVE) { // Value is 1. if (NbrFactorsNorm == 0) { w("No gaussian prime divides this number"); } } else { // Value is -1. w("<li>-1</li>"); } } else if (ImValue.sign == SIGN_POSITIVE) { w("<li>i</li>"); } else { w("<li>-i</li>"); } w("</ul>"); }
void DiscreteLogarithm(void) { BigInteger groupOrder, subGroupOrder, powSubGroupOrder, powSubGroupOrderBak; BigInteger Exponent, runningExp, baseExp, mod; BigInteger logar, logarMult, runningExpBase; BigInteger currentExp; int indexBase, indexExp; int index, expon; limb addA, addB, addA2, addB2; limb mult1, mult2; double magnitude, firstLimit, secondLimit; long long brentK, brentR; unsigned char EndPollardBrentRho; int nbrLimbs; struct sFactors *pstFactors; enum eLogMachineState logMachineState; char *ptr; #ifdef __EMSCRIPTEN__ lModularMult = 0; #endif NumberLength = modulus.nbrLimbs; if (!TestBigNbrEqual(&LastModulus, &modulus)) { CompressBigInteger(nbrToFactor, &modulus); Bin2Dec(modulus.limbs, tofactorDec, modulus.nbrLimbs, groupLen); factor(&modulus, nbrToFactor, factorsMod, astFactorsMod, NULL); NbrFactorsMod = astFactorsMod[0].multiplicity; } intToBigInteger(&DiscreteLog, 0); // DiscreteLog <- 0 intToBigInteger(&DiscreteLogPeriod, 1); // DiscreteLogPeriod <- 1 for (index = 1; index <= NbrFactorsMod; index++) { int mostSignificantDword, leastSignificantDword; int NbrFactors; int *ptrPrime; int multiplicity; ptrPrime = astFactorsMod[index].ptrFactor; NumberLength = *ptrPrime; UncompressBigInteger(ptrPrime, &groupOrder); groupOrder.sign = SIGN_POSITIVE; BigIntRemainder(&base, &groupOrder, &tmpBase); if (tmpBase.nbrLimbs == 1 && tmpBase.limbs[0].x == 0) { // modulus and base are not relatively prime. int ctr; multiplicity = astFactorsMod[index].multiplicity; CopyBigInt(&bigNbrA, &power); for (ctr = multiplicity; ctr > 0; ctr--) { BigIntRemainder(&bigNbrA, &groupOrder, &bigNbrB); if (bigNbrB.nbrLimbs != 1 || bigNbrB.limbs[0].x != 0) { // Exit loop if integer division cannot be performed break; } BigIntDivide(&bigNbrA, &groupOrder, &bigNbrB); CopyBigInt(&bigNbrA, &bigNbrB); } if (ctr == 0) { // Power is multiple of prime^exp. continue; } // Compute prime^mutliplicity. BigIntPowerIntExp(&groupOrder, multiplicity, &tmp2); BigIntRemainder(&base, &tmp2, &tmpBase); // Get tentative exponent. ctr = multiplicity - ctr; intToBigInteger(&bigNbrB, ctr); // Convert exponent to big integer. NumberLength = tmp2.nbrLimbs; memcpy(TestNbr, tmp2.limbs, (NumberLength + 1) * sizeof(limb)); GetMontgomeryParms(NumberLength); BigIntModularPower(&tmpBase, &bigNbrB, &bigNbrA); BigIntRemainder(&power, &tmp2, &bigNbrB); BigIntSubt(&bigNbrA, &bigNbrB, &bigNbrA); if (bigNbrA.nbrLimbs == 1 && bigNbrA.limbs[0].x == 0) { intToBigInteger(&DiscreteLog, ctr); // DiscreteLog <- exponent intToBigInteger(&DiscreteLogPeriod, 0); // DiscreteLogPeriod <- 0 break; } showText("There is no discrete logarithm"); DiscreteLogPeriod.sign = SIGN_NEGATIVE; return; } else { // modulus and base are relatively prime. BigIntRemainder(&power, &groupOrder, &bigNbrB); if (bigNbrB.nbrLimbs == 1 && bigNbrB.limbs[0].x == 0) { // power is multiple of prime. Error. showText("There is no discrete logarithm"); DiscreteLogPeriod.sign = SIGN_NEGATIVE; return; } } CompressLimbsBigInteger(baseMontg, &tmpBase); BigIntRemainder(&power, &groupOrder, &tmpBase); CompressLimbsBigInteger(powerMontg, &tmpBase); // Compute group order as the prime minus 1. groupOrder.limbs[0].x--; showText("Computing discrete logarithm..."); CompressBigInteger(nbrToFactor, &groupOrder); factor(&groupOrder, nbrToFactor, factorsGO, astFactorsGO, NULL); // factor groupOrder. NbrFactors = astFactorsGO[0].multiplicity; NumberLength = *ptrPrime; UncompressBigInteger(ptrPrime, &mod); intToBigInteger(&logar, 0); // logar <- 0 intToBigInteger(&logarMult, 1); // logarMult <- 1 NumberLength = mod.nbrLimbs; memcpy(TestNbr, mod.limbs, NumberLength * sizeof(limb)); TestNbr[NumberLength].x = 0; // yieldFreq = 1000000 / (NumberLength*NumberLength); GetMontgomeryParms(NumberLength); #if 0 char *ptrText = textExp; strcpy(ptrText, "<p>NumberLength (2) = "); ptrText = ptrText + strlen(ptrText); int2dec(&ptrText, NumberLength); strcpy(ptrText, "</p>"); DiscreteLogPeriod.sign = SIGN_NEGATIVE; return; #endif // Convert base and power to Montgomery notation. modmult(baseMontg, MontgomeryMultR2, baseMontg); modmult(powerMontg, MontgomeryMultR2, powerMontg); mostSignificantDword = NumberLength - 1; if (NumberLength == 1) { leastSignificantDword = NumberLength - 1; firstLimit = (double)TestNbr[leastSignificantDword].x / 3; } else { leastSignificantDword = NumberLength - 2; firstLimit = ((double)TestNbr[mostSignificantDword].x * LIMB_RANGE + TestNbr[leastSignificantDword].x) / 3; } secondLimit = firstLimit * 2; for (indexBase = 0; indexBase < NbrFactors; indexBase++) { NumberLength = *astFactorsGO[indexBase + 1].ptrFactor; UncompressBigInteger(astFactorsGO[indexBase + 1].ptrFactor, &subGroupOrder); subGroupOrder.sign = SIGN_POSITIVE; strcpy(textExp, "Computing discrete logarithm in subgroup of "); Bin2Dec(subGroupOrder.limbs, textExp + strlen(textExp), subGroupOrder.nbrLimbs, groupLen); ptr = textExp + strlen(textExp); if (astFactorsGO[indexBase + 1].multiplicity > 1) { *ptr++ = '<'; *ptr++ = 's'; *ptr++ = 'u'; *ptr++ = 'p'; *ptr++ = '>'; int2dec(&ptr, astFactorsGO[indexBase + 1].multiplicity); *ptr++ = '<'; *ptr++ = '/'; *ptr++ = 's'; *ptr++ = 'u'; *ptr++ = 'p'; *ptr++ = '>'; } strcpy(ptr, " elements."); showText(textExp); NumberLength = mod.nbrLimbs; memcpy(TestNbr, mod.limbs, NumberLength * sizeof(limb)); NumberLengthOther = subGroupOrder.nbrLimbs; memcpy(TestNbrOther, subGroupOrder.limbs, NumberLengthOther * sizeof(limb)); TestNbr[NumberLength].x = 0; GetMontgomeryParms(NumberLength); nbrLimbs = subGroupOrder.nbrLimbs; dN = (double)subGroupOrder.limbs[nbrLimbs - 1].x; if (nbrLimbs > 1) { dN += (double)subGroupOrder.limbs[nbrLimbs - 2].x / LIMB_RANGE; if (nbrLimbs > 2) { dN += (double)subGroupOrder.limbs[nbrLimbs - 3].x / LIMB_RANGE / LIMB_RANGE; } } CopyBigInt(&baseExp, &groupOrder); // Check whether base is primitive root. BigIntDivide(&groupOrder, &subGroupOrder, &tmpBase); modPow(baseMontg, tmpBase.limbs, tmpBase.nbrLimbs, primRootPwr); if (!memcmp(primRootPwr, MontgomeryMultR1, NumberLength * sizeof(limb))) { // Power is one, so it is not a primitive root. logMachineState = CALC_LOG_BASE; // Find primitive root primRoot[0].x = 1; if (NumberLength > 1) { memset(&primRoot[1], 0, (NumberLength - 1) * sizeof(limb)); } do { primRoot[0].x++; modPow(primRoot, tmpBase.limbs, tmpBase.nbrLimbs, primRootPwr); } while (!memcmp(primRootPwr, MontgomeryMultR1, NumberLength * sizeof(limb))); } else { // Power is not 1, so the base is a primitive root. logMachineState = BASE_PRIMITIVE_ROOT; memcpy(primRoot, baseMontg, NumberLength * sizeof(limb)); } for (;;) { // Calculate discrete logarithm in subgroup. runningExp.nbrLimbs = 1; // runningExp <- 0 runningExp.limbs[0].x = 0; runningExp.sign = SIGN_POSITIVE; powSubGroupOrder.nbrLimbs = 1; // powSubGroupOrder <- 1 powSubGroupOrder.limbs[0].x = 1; powSubGroupOrder.sign = SIGN_POSITIVE; CopyBigInt(¤tExp, &groupOrder); if (logMachineState == BASE_PRIMITIVE_ROOT) { memcpy(basePHMontg, baseMontg, NumberLength * sizeof(limb)); memcpy(currPowerMontg, powerMontg, NumberLength * sizeof(limb)); } else if (logMachineState == CALC_LOG_BASE) { memcpy(basePHMontg, primRoot, NumberLength * sizeof(limb)); memcpy(currPowerMontg, baseMontg, NumberLength * sizeof(limb)); } else { // logMachineState == CALC_LOG_POWER memcpy(primRoot, basePHMontg, NumberLength * sizeof(limb)); memcpy(currPowerMontg, powerMontg, NumberLength * sizeof(limb)); } for (indexExp = 0; indexExp < astFactorsGO[indexBase + 1].multiplicity; indexExp++) { /* PH below comes from Pohlig-Hellman algorithm */ BigIntDivide(¤tExp, &subGroupOrder, ¤tExp); modPow(currPowerMontg, currentExp.limbs, currentExp.nbrLimbs, powerPHMontg); BigIntDivide(&baseExp, &subGroupOrder, &baseExp); if (subGroupOrder.nbrLimbs == 1 && subGroupOrder.limbs[0].x < 20) { // subGroupOrder less than 20. if (!ComputeDLogModSubGroupOrder(indexBase, indexExp, &Exponent, &subGroupOrder)) { return; } } else { // Use Pollard's rho method with Brent's modification memcpy(nbrPower, powerPHMontg, NumberLength * sizeof(limb)); memcpy(nbrBase, primRootPwr, NumberLength * sizeof(limb)); memcpy(nbrR2, nbrBase, NumberLength * sizeof(limb)); memset(nbrA2, 0, NumberLength * sizeof(limb)); memset(nbrB2, 0, NumberLength * sizeof(limb)); nbrB2[0].x = 1; addA2.x = addB2.x = 0; mult2.x = 1; brentR = 1; brentK = 0; EndPollardBrentRho = FALSE; do { memcpy(nbrR, nbrR2, NumberLength * sizeof(limb)); memcpy(nbrA, nbrA2, NumberLength * sizeof(limb)); memcpy(nbrB, nbrB2, NumberLength * sizeof(limb)); addA = addA2; addB = addB2; mult1 = mult2; brentR *= 2; do { brentK++; if (NumberLength == 1) { magnitude = (double)nbrR2[leastSignificantDword].x; } else { magnitude = (double)nbrR2[mostSignificantDword].x * LIMB_RANGE + nbrR2[leastSignificantDword].x; } if (magnitude < firstLimit) { modmult(nbrR2, nbrPower, nbrROther); addA2.x++; } else if (magnitude < secondLimit) { modmult(nbrR2, nbrR2, nbrROther); mult2.x *= 2; addA2.x *= 2; addB2.x *= 2; } else { modmult(nbrR2, nbrBase, nbrROther); addB2.x++; } // Exchange nbrR2 and nbrROther memcpy(nbrTemp, nbrR2, NumberLength * sizeof(limb)); memcpy(nbrR2, nbrROther, NumberLength * sizeof(limb)); memcpy(nbrROther, nbrTemp, NumberLength * sizeof(limb)); if (addA2.x >= (int)(LIMB_RANGE / 2) || addB2.x >= (int)(LIMB_RANGE / 2) || mult2.x >= (int)(LIMB_RANGE / 2)) { // nbrA2 <- (nbrA2 * mult2 + addA2) % subGroupOrder AdjustExponent(nbrA2, mult2, addA2, &subGroupOrder); // nbrB2 <- (nbrB2 * mult2 + addB2) % subGroupOrder AdjustExponent(nbrB2, mult2, addB2, &subGroupOrder); mult2.x = 1; addA2.x = addB2.x = 0; } if (!memcmp(nbrR, nbrR2, NumberLength * sizeof(limb))) { EndPollardBrentRho = TRUE; break; } } while (brentK < brentR); } while (EndPollardBrentRho == FALSE); ExchangeMods(); // TestNbr <- subGroupOrder // nbrA <- (nbrA * mult1 + addA) % subGroupOrder AdjustExponent(nbrA, mult1, addA, &subGroupOrder); // nbrB <- (nbrB * mult1 + addB) % subGroupOrder AdjustExponent(nbrB, mult1, addB, &subGroupOrder); // nbrA2 <- (nbrA * mult2 + addA2) % subGroupOrder AdjustExponent(nbrA2, mult2, addA2, &subGroupOrder); // nbrB2 <- (nbrA * mult2 + addB2) % subGroupOrder AdjustExponent(nbrB2, mult2, addB2, &subGroupOrder); // nbrB <- (nbrB2 - nbrB) % subGroupOrder SubtBigNbrMod(nbrB2, nbrB, nbrB); SubtBigNbrMod(nbrA, nbrA2, nbrA); if (BigNbrIsZero(nbrA)) { // Denominator is zero, so rho does not work. ExchangeMods(); // TestNbr <- modulus if (!ComputeDLogModSubGroupOrder(indexBase, indexExp, &Exponent, &subGroupOrder)) { return; // Cannot compute discrete logarithm. } } else { // Exponent <- (nbrB / nbrA) (mod subGroupOrder) UncompressLimbsBigInteger(nbrA, &bigNbrA); UncompressLimbsBigInteger(nbrB, &bigNbrB); BigIntModularDivisionSaveTestNbr(&bigNbrB, &bigNbrA, &subGroupOrder, &Exponent); Exponent.sign = SIGN_POSITIVE; ExchangeMods(); // TestNbr <- modulus } } modPow(primRoot, Exponent.limbs, Exponent.nbrLimbs, tmpBase.limbs); ModInvBigNbr(tmpBase.limbs, tmpBase.limbs, TestNbr, NumberLength); modmult(tmpBase.limbs, currPowerMontg, currPowerMontg); BigIntMultiply(&Exponent, &powSubGroupOrder, &tmpBase); BigIntAdd(&runningExp, &tmpBase, &runningExp); BigIntMultiply(&powSubGroupOrder, &subGroupOrder, &powSubGroupOrder); modPow(primRoot, subGroupOrder.limbs, subGroupOrder.nbrLimbs, tmpBase.limbs); memcpy(primRoot, tmpBase.limbs, NumberLength * sizeof(limb)); } if (logMachineState == BASE_PRIMITIVE_ROOT) { // Discrete logarithm was determined for this subgroup. ExponentsGOComputed[indexBase] = astFactorsGO[indexBase + 1].multiplicity; break; } if (logMachineState == CALC_LOG_BASE) { CopyBigInt(&runningExpBase, &runningExp); logMachineState = CALC_LOG_POWER; } else { // Set powSubGroupOrderBak to powSubGroupOrder. // if runningExpBase is not multiple of subGroupOrder, // discrete logarithm is runningExp/runningExpBase mod powSubGroupOrderBak. // Otherwise if runningExp is multiple of subGroupOrder, there is no logarithm. // Otherwise, divide runningExp, runnignExpBase and powSubGroupOrderBak by subGroupOrder and repeat. ExponentsGOComputed[indexBase] = astFactorsGO[indexBase + 1].multiplicity; CopyBigInt(&powSubGroupOrderBak, &powSubGroupOrder); do { BigIntRemainder(&runningExpBase, &subGroupOrder, &tmpBase); if (tmpBase.nbrLimbs > 1 || tmpBase.limbs[0].x != 0) { // runningExpBase is not multiple of subGroupOrder BigIntModularDivisionSaveTestNbr(&runningExp, &runningExpBase, &powSubGroupOrderBak, &tmpBase); CopyBigInt(&runningExp, &tmpBase); break; } BigIntRemainder(&runningExp, &subGroupOrder, &tmpBase); if (tmpBase.nbrLimbs > 1 || tmpBase.limbs[0].x != 0) { // runningExpBase is not multiple of subGroupOrder showText("There is no discrete logarithm"); DiscreteLogPeriod.sign = SIGN_NEGATIVE; return; } BigIntDivide(&runningExp, &subGroupOrder, &tmpBase); CopyBigInt(&runningExp, &tmpBase); BigIntDivide(&runningExpBase, &subGroupOrder, &tmpBase); CopyBigInt(&runningExpBase, &tmpBase); BigIntDivide(&powSubGroupOrderBak, &subGroupOrder, &tmpBase); CopyBigInt(&powSubGroupOrderBak, &tmpBase); ExponentsGOComputed[indexBase]--; if (tmpBase.nbrLimbs == 1 && tmpBase.limbs[0].x == 1) { break; } BigIntRemainder(&runningExpBase, &subGroupOrder, &tmpBase); } while (tmpBase.nbrLimbs == 1 && tmpBase.limbs[0].x == 0); CopyBigInt(&powSubGroupOrder, &powSubGroupOrderBak); // The logarithm is runningExp / runningExpBase mod powSubGroupOrder // When powSubGroupOrder is even, we cannot use Montgomery. if (powSubGroupOrder.limbs[0].x & 1) { // powSubGroupOrder is odd. BigIntModularDivisionSaveTestNbr(&runningExp, &runningExpBase, &powSubGroupOrder, &tmpBase); CopyBigInt(&runningExp, &tmpBase); } else { // powSubGroupOrder is even (power of 2). NumberLength = powSubGroupOrder.nbrLimbs; CompressLimbsBigInteger(nbrB, &runningExpBase); ComputeInversePower2(nbrB, nbrA, nbrB2); // nbrB2 is auxiliary var. CompressLimbsBigInteger(nbrB, &runningExp); multiply(nbrA, nbrB, nbrA, NumberLength, NULL); // nbrA <- quotient. UncompressLimbsBigInteger(nbrA, &runningExp); } break; } } CopyBigInt(&nbrV[indexBase], &runningExp); NumberLength = powSubGroupOrder.nbrLimbs; memcpy(TestNbr, powSubGroupOrder.limbs, NumberLength * sizeof(limb)); TestNbr[NumberLength].x = 0; GetMontgomeryParms(NumberLength); for (indexExp = 0; indexExp < indexBase; indexExp++) { // nbrV[indexBase] <- (nbrV[indexBase] - nbrV[indexExp])* // modinv(PrimesGO[indexExp]^(ExponentsGO[indexExp]), // powSubGroupOrder) NumberLength = mod.nbrLimbs; BigIntSubt(&nbrV[indexBase], &nbrV[indexExp], &nbrV[indexBase]); BigIntRemainder(&nbrV[indexBase], &powSubGroupOrder, &nbrV[indexBase]); if (nbrV[indexBase].sign == SIGN_NEGATIVE) { BigIntAdd(&nbrV[indexBase], &powSubGroupOrder, &nbrV[indexBase]); } pstFactors = &astFactorsGO[indexExp + 1]; UncompressBigInteger(pstFactors->ptrFactor, &tmpBase); BigIntPowerIntExp(&tmpBase, ExponentsGOComputed[indexExp], &tmpBase); BigIntRemainder(&tmpBase, &powSubGroupOrder, &tmpBase); NumberLength = powSubGroupOrder.nbrLimbs; CompressLimbsBigInteger(tmp2.limbs, &tmpBase); modmult(tmp2.limbs, MontgomeryMultR2, tmp2.limbs); if (NumberLength > 1 || TestNbr[0].x != 1) { // If TestNbr != 1 ... ModInvBigNbr(tmp2.limbs, tmp2.limbs, TestNbr, NumberLength); } tmpBase.limbs[0].x = 1; memset(&tmpBase.limbs[1], 0, (NumberLength - 1) * sizeof(limb)); modmult(tmpBase.limbs, tmp2.limbs, tmp2.limbs); UncompressLimbsBigInteger(tmp2.limbs, &tmpBase); BigIntMultiply(&tmpBase, &nbrV[indexBase], &nbrV[indexBase]); } BigIntRemainder(&nbrV[indexBase], &powSubGroupOrder, &nbrV[indexBase]); BigIntMultiply(&nbrV[indexBase], &logarMult, &tmpBase); BigIntAdd(&logar, &tmpBase, &logar); BigIntMultiply(&logarMult, &powSubGroupOrder, &logarMult); } multiplicity = astFactorsMod[index].multiplicity; UncompressBigInteger(ptrPrime, &bigNbrB); expon = 1; if (bigNbrB.nbrLimbs == 1 && bigNbrB.limbs[0].x == 2) { // Prime factor is 2. Base and power are odd at this moment. int lsbBase = base.limbs[0].x; int lsbPower = power.limbs[0].x; if (multiplicity > 1) { int mask = (multiplicity == 2? 3 : 7); expon = (multiplicity == 2 ? 2 : 3); if ((lsbPower & mask) == 1) { intToBigInteger(&logar, 0); intToBigInteger(&logarMult, (lsbBase == 1 ? 1 : 2)); } else if (((lsbPower - lsbBase) & mask) == 0) { intToBigInteger(&logar, 1); intToBigInteger(&logarMult, 2); } else { showText("There is no discrete logarithm"); DiscreteLogPeriod.sign = SIGN_NEGATIVE; return; } } } for (; expon < multiplicity; expon++) { // Repeated factor. // L = logar, LM = logarMult // B = base, P = power, p = prime // B^n = P (mod p^(k+1)) -> n = L + m*LM m = ? // B^(L + m*LM) = P // (B^LM) ^ m = P*B^(-L) // B^LM = r*p^k + 1, P*B^(-L) = s*p^k + 1 // (r*p^k + 1)^m = s*p^k + 1 // From binomial theorem: m = s / r (mod p) // If r = 0 and s != 0 there is no solution. // If r = 0 and s = 0 do not change LM. BigIntPowerIntExp(&bigNbrB, expon + 1, &bigNbrA); NumberLength = bigNbrA.nbrLimbs; memcpy(TestNbr, bigNbrA.limbs, NumberLength * sizeof(limb)); GetMontgomeryParms(NumberLength); BigIntRemainder(&base, &bigNbrA, &tmpBase); CompressLimbsBigInteger(baseMontg, &tmpBase); modmult(baseMontg, MontgomeryMultR2, baseMontg); modPow(baseMontg, logarMult.limbs, logarMult.nbrLimbs, primRootPwr); // B^LM tmpBase.limbs[0].x = 1; // Convert from Montgomery to standard notation. memset(&tmpBase.limbs[1], 0, (NumberLength - 1) * sizeof(limb)); modmult(primRootPwr, tmpBase.limbs, primRootPwr); // B^LM ModInvBigNbr(baseMontg, tmpBase.limbs, TestNbr, NumberLength); // B^(-1) modPow(tmpBase.limbs, logar.limbs, logar.nbrLimbs, primRoot); // B^(-L) BigIntRemainder(&power, &bigNbrA, &tmpBase); CompressLimbsBigInteger(tmp2.limbs, &tmpBase); modmult(primRoot, tmp2.limbs, primRoot); // P*B^(-L) BigIntDivide(&bigNbrA, &bigNbrB, &tmpBase); UncompressLimbsBigInteger(primRootPwr, &tmp2); BigIntDivide(&tmp2, &tmpBase, &bigNbrA); // s UncompressLimbsBigInteger(primRoot, &baseModGO); // Use baseMontGO as temp var. BigIntDivide(&baseModGO, &tmpBase, &tmp2); // r if (bigNbrA.nbrLimbs == 1 && bigNbrA.limbs[0].x == 0) { // r equals zero. if (tmp2.nbrLimbs != 1 || tmp2.limbs[0].x != 0) { // s does not equal zero. showText("There is no discrete logarithm"); DiscreteLogPeriod.sign = SIGN_NEGATIVE; return; } } else { // r does not equal zero. BigIntModularDivisionSaveTestNbr(&tmp2, &bigNbrA, &bigNbrB, &tmpBase); // m BigIntMultiply(&tmpBase, &logarMult, &tmp2); BigIntAdd(&logar, &tmp2, &logar); BigIntMultiply(&logarMult, &bigNbrB, &logarMult); } } // Based on logar and logarMult, compute DiscreteLog and DiscreteLogPeriod // using the following formulas, that can be deduced from the Chinese // Remainder Theorem: // L = logar, LM = logarMult, DL = DiscreteLog, DLP = DiscreteLogPeriod. // The modular implementation does not allow operating with even moduli. // // g <- gcd(LM, DLP) // if (L%g != DL%g) there is no discrete logarithm, so go out. // h <- LM / g // if h is odd: // t <- (L - DL) / DLP (mod h) // t <- DLP * t + DL // else // i <- DLP / g // t <- (DL - L) / LM (mod i) // t <- LM * t + L // endif // DLP <- DLP * h // DL <- t % DLP BigIntGcd(&logarMult, &DiscreteLogPeriod, &tmpBase); BigIntRemainder(&logar, &tmpBase, &bigNbrA); BigIntRemainder(&DiscreteLog, &tmpBase, &bigNbrB); if (!TestBigNbrEqual(&bigNbrA, &bigNbrB)) { showText("There is no discrete logarithm"); DiscreteLogPeriod.sign = SIGN_NEGATIVE; return; } BigIntDivide(&logarMult, &tmpBase, &tmp2); if (tmp2.limbs[0].x & 1) { // h is odd. BigIntSubt(&logar, &DiscreteLog, &tmpBase); BigIntModularDivisionSaveTestNbr(&tmpBase, &DiscreteLogPeriod, &tmp2, &bigNbrA); BigIntMultiply(&DiscreteLogPeriod, &bigNbrA, &tmpBase); BigIntAdd(&tmpBase, &DiscreteLog, &tmpBase); } else { // h is even. BigIntDivide(&DiscreteLogPeriod, &tmpBase, &bigNbrB); BigIntSubt(&DiscreteLog, &logar, &tmpBase); BigIntModularDivisionSaveTestNbr(&tmpBase, &logarMult, &bigNbrB, &bigNbrA); BigIntMultiply(&logarMult, &bigNbrA, &tmpBase); BigIntAdd(&tmpBase, &logar, &tmpBase); } BigIntMultiply(&DiscreteLogPeriod, &tmp2, &DiscreteLogPeriod); BigIntRemainder(&tmpBase, &DiscreteLogPeriod, &DiscreteLog); } #if 0 textExp.setText(DiscreteLog.toString()); textPeriod.setText(DiscreteLogPeriod.toString()); long t = OldTimeElapsed / 1000; labelStatus.setText("Time elapsed: " + t / 86400 + "d " + (t % 86400) / 3600 + "h " + ((t % 3600) / 60) + "m " + (t % 60) + "s mod mult: " + lModularMult); #endif }
int main(){ int T; scanf("%d", &T); int N; vi A; std::vector<pii> studs; std::vector<pii> studs_pairs; std::vector<pii> memo; while(T--){ scanf("%d", &N); for(int i = 0; i < N; i++){ int x; scanf("%d", &x); A.push_back(x); } for(int i = 0; i < N; i++){ for(int j = i + 1; j < N; j++){ int val_1 = modPow(A[i], A[j]); int val_2 = modPow(A[j], A[i]); int val = min(val_1, val_2); studs.push_back(std::make_pair(studs.size(), val)); studs_pairs.push_back(std::make_pair(A[i], A[j])); } } std::sort(studs.begin(), studs.end(), myfunction); bool flag = true; while(flag){ pii& x = studs.back(); pii& y = studs_pairs[x.first]; vi list1, list2; for(std::vector<pii>::iterator it = memo.begin(); it != memo.end(); it++){ if(y.first == it->first) list1.push_back(it->second); else if(y.first == it->second) list1.push_back(it->first); if(y.second == it->first) list2.push_back(it->second); else if(y.second == it->second) list2.push_back(it->first); } for(vi::iterator it = list1.begin(); it != list1.end(); it++){ for(vi::iterator jt = list2.begin(); jt != list2.end(); jt++){ if(*it == *jt){ flag = false; break; } } } if(flag){ studs.pop_back(); memo.push_back(y); } } A.clear(); memo.clear(); printf("%d\n", studs.back().second); } }
void SecretShare::modPow(mpz_t* result, mpz_t* base, long exponent, int size){ for(int i=0; i<size; ++i) modPow(result[i],base[i],exponent); }
template <typename Integer> Integer factorQuadratic(Integer N){ const int FCount = 6; const int TCount = 6; Integer F[FCount] = {-1}; Integer prime = newPrime<Integer>(true); for(int i = 1; i < FCount;){ if (modPow(N, (prime-Integer(1))/Integer(2), prime) == Integer(1)) F[i++] = prime; prime = newPrime<Integer>(); } Integer M = sqrt(N); std::vector< std::pair< std::pair<Integer, Integer>, std::pair< std::bitset<FCount>, std::vector<Integer> > > > pairSet; Integer X = 0; auto Q = [M, N](Integer X){return (X+M)*(X+M)-N;}; auto nextX = [](Integer X){if (X < 0) return (-X)+1; else if (X > 0) return -X; else return Integer(1);}; while (pairSet.size() < TCount+1){ Integer B = Q(X); Integer B_ = B; std::bitset<FCount> Bfactormod2; std::vector<Integer> Bfactor(FCount); if (B < Integer(0)) Bfactormod2.flip(0), B = -B, Bfactor[0] = 1; for(int i = 1; i < FCount && B != 1; i++){ while (B % F[i] == 0) Bfactormod2.flip(i), B/=F[i], Bfactor[i]++; } if (B == 1){ pairSet.push_back(std::make_pair(std::make_pair(X+M, B_), std::make_pair(Bfactormod2, Bfactor))); } X = nextX(X); } for(int i = 1; i < 1<<(TCount+1); i++){ std::bitset<FCount> res; std::bitset<TCount+1> mask(i); for(int j = 0; j < TCount+1; j++){ if (mask[j]) res ^= pairSet[j].second.first; } if (res == 0){ Integer x(1); for(int j = 0; j < TCount+1; j++) if (mask[j]) x = (x * pairSet[j].first.first) % N; std::vector<Integer> l(FCount); for(int i = 0; i < FCount; i++){ for(int j = 0; j < TCount+1; j++){ if (mask[j]) l[i] += pairSet[j].second.second[i]; } l[i] /= 2; } Integer y = 1; for(int i = 0; i < FCount; i++) y = (y * modPow(F[i], l[i], N))%N; if (x != y && x != -y){ Integer T = x-y; Integer res = GCD(x-y, N); if (res == Integer(1) || res == N || res == Integer(-1)) continue; return res; } } } return Integer(1); }
template <typename Integer> static Integer modPow(Integer val, Integer deg, Integer mod){ if (deg == Integer(0)) return Integer(1); else if (deg%2 == 0) return (modPow(val, deg/Integer(2), mod) * modPow(val, deg/Integer(2), mod)) % mod; else return (((modPow(val, deg/Integer(2), mod)*modPow(val, deg/Integer(2), mod))%mod)*val) % mod; }