Pollard Rho 在不太大的输入上崩溃

Pollard Rho crashes on inputs that are not too big

本文关键字:输入 崩溃 Rho Pollard      更新时间:2023-10-16

我实现了维基百科上给出的Pollard Rho算法

x ← 2; y ← 2; d ← 1
while d = 1:
x ← g(x)
y ← g(g(y))
d ← gcd(|x - y|, n)
if d = n: 
return failure
else:
return d

大输入给出错误:

GNU MP:无法分配内存(大小=4294950944)

这是我的实现

mpz_class factor(mpz_class num)
{
mpz_class x(2), y(2), d(1);
while(d == 1)
{
x = polynomial(x);
y = polynomial(polynomial(y));
mpz_class diff = x - y;
if(diff < 0)
{
diff *= -1;
}
mpz_gcd(d.get_mpz_t(), diff.get_mpz_t(), num.get_mpz_t());
}
if(d == num)
{
return -1;//failure
}
else
{
return d;//found factor
}
}
mpz_class polynomial (mpz_class x)
{
return ((x * x) + 1);
}

它适用于 121 等输入,但在5540987时崩溃。我做错了什么吗?有没有办法改善这一点,以便可以分解这些数字?我已经看到一些似乎使用多项式((x*x)%N+c)%N的实现(注意额外的mod n)。这是否有效,因为可以使用任何多项式?

有两个模运算是多余的,但有一个可以精确地解决数字爆炸的问题,除非算法很早就终止(对于 121 也是如此)。

这是否有效,因为可以使用任何多项式?

它更微妙一些,将模运算放入混合中并不是真正的"任何多项式"的情况。关键是算法寻找的是某个序列中的两个值x[i]x[j]i != j使得abs(x[i] - x[j])p的倍数(其中N = pqpq都不是1),换句话说,abs(x[i] - x[j]) mod p = 0x[i] ≡ x[j] mod p。在这一点上,当观察模p时,在序列中发现了一个循环,重要的是,如果x[i] != x[j]那么它们的差是p的非零倍数,这给了从N中提取一个因子的机会。至少如果它们的差异不是N的倍数(在这种情况下,GCD 的结果本身将是N的,并且没有因素出来)。

因此,纯粹从数学角度看,模N步骤在理论上是不必要的,循环模p在没有这种"帮助"的情况下发生。但这是可能的N = pq如果我们减少序列模N,那么它的属性模p不会受到干扰,算法仍然有效。更重要的是,归约模N实际上非常重要,因为它阻止了所涉及的数字变得不切实际的大,否则这不仅会减慢算法的速度,而且最终会在实际(有限大小)硬件上失败。

这是很多理论理由,实现非常简单,

mpz_class polynomial (mpz_class x, mpz_class num)
{
return ((x * x) + 1) % num;
}