the gnfs is the most efficient algorithm for factoring numbers formed of equal composites.
But it’s sequential/Linea Algebra parts mean (If I’m not wrong), that it requires at least 10 minutes on current hardware to factor semi‑primes formed of composites of equal length (in the case of 382 bits semi‑primes).
Are there less efficient algorithms but by being more parallelizable, that would allow to solve batch of such semi‑primes faster using more resources ? (the batch is sequential : a number needs to be factored by a participant to know the next number to solve)…
For more information, here’s in pseudocode how the semiprime needs to be chosen by the person who submits both the semiprime/factors (the real program contains code so that the semiprime is chosen efficiently and that factoring is the issue) :
uint1024 w = hash(common_challenge_to_participants);
//Check that |common_challenge_to_participants| <= \tilde{n} = 16 * |n|_2.
uint64_t abs_offset = (chosen_wOffset > 0) ? common_challenge_to_participants.wOffset : -common_challenge_to_participants.wOffset;
if (abs_offset > 16 * common_challenge_to_participants.common_target_nBits) { //where target_nbits is between 350 to 400
LogPrintf("invalid wOffset\n");
return false;
}
//Get the semiprime from random seed
mpz_t n, W;
mpz_init(n);
mpz_init(W);
mpz_import(W, 16, -1, 8, 0, 0, w.u64_begin()); //cast w to W
//Add the offset to w to find the semiprime submitted: n = w + offset
if (common_challenge_to_participants.wOffset >= 0) {
mpz_add_ui(n, W, abs_offset);
} else {
mpz_sub_ui(n, W, abs_offset);
}
//Clear memory for W.
mpz_clear(W);
//Check the number n has nBits
if (mpz_sizeinbase(n, 2) != common_challenge_to_participants.common_target_nBits) {
LogPrintf("invalid nBits");
mpz_clear(n);
return false;
}
//Divide the factor submitted by N
mpz_t nP1, nP2;
mpz_init(nP1);
mpz_init(nP2);
mpz_import(nP1, 16, -1, 8, 0, 0, common_challenge_to_participants.nP1.u64_begin());
mpz_tdiv_q(nP2, n, nP1);
//Check the bitsizes are as expected
const uint16_t nP1_bitsize = mpz_sizeinbase(nP1, 2);
const uint16_t expected_bitsize = (common_challenge_to_participants.common_target_nBits >> 1) + (common_challenge_to_participants.common_target_nBits & 1);
if (nP1_bitsize != expected_bitsize) {
LogPrintf("nP1 expected bitsize=%s, actual size=%s\n", nP1_bitsize, expected_bitsize);
mpz_clear(n);
mpz_clear(nP1);
mpz_clear(nP2);
return false;
}
//Check nP1 is a factor
mpz_t n_check;
mpz_init(n_check);
mpz_mul(n_check, nP1, nP2);
//Check that nP1*nP2 == n.
if (mpz_cmp(n_check, n) != 0) {
LogPrintf("nP1 does not divide N. N=%s nP1=%s\n", mpz_get_str(NULL, 10, n), mpz_get_str(NULL, 10, nP1));
mpz_clear(n);
mpz_clear(nP1);
mpz_clear(nP2);
mpz_clear(n_check);
return false;
}
//Check that nP1 <= nP2.
if (mpz_cmp(nP1, nP2) > 0) {
LogPrintf("error: nP1 must be the smallest factor. N=%s nP1=%s\n", mpz_get_str(NULL, 10, n), mpz_get_str(NULL, 10, nP1));
mpz_clear(n);
mpz_clear(nP1);
mpz_clear(nP2);
mpz_clear(n_check);
return false;
}
//Clear memory
mpz_clear(n);
mpz_clear(n_check);
//Test nP1 and nP2 for primality.
int is_nP1_prime = mpz_probab_prime_p(nP1, params.MillerRabinRounds);
int is_nP2_prime = mpz_probab_prime_p(nP2, params.MillerRabinRounds);
//Clear memory
mpz_clear(nP1);
mpz_clear(nP2);
//Check they are both prime
if (is_nP1_prime == 0 || is_nP2_prime == 0) {
LogPrintf("At least 1 composite factor found, rejected.\n");
return false;
}
return true;
- Update : I know about the other question. But My problem is doing it in a specific very short timeframe.