数学体操I——大数分解算法学习
分解质因数的方法们
还在施工学习,学了再补充。
本文探讨的仅为分解\(n=pq\)(\(p\),\(q\)均为素数)这种形式的问题。
枚举
整一个质数表,挨个去 世 试。
在线的网站&工具箱
在线的分解质因数网站——factordb
工具箱:yafu
用法可以看这个博客:RSA因数分解工具yafu下载地址及使用方法介绍
连分数分解
在初等数论中,我们可以利用连分数分解法来寻找大整数的因子。
python脚本:
from math import sqrt,floor,gcd
#判断是否为平方数
def is_square(n):
t = int(sqrt(n))
return t*t == n
n = #要分解的数
seq_P, seq_Q=0, 1
a0 = floor(sqrt(n))
seq_a= [a0]
seq_p = [0,a0]
i = 1
while True:
#P_{k},Q_{k}序列
seq_P = seq_a[0]*seq_Q-seq_P
seq_Q = divmod(n-seq_P**2,seq_Q)[0]
t = (seq_P+sqrt(n))/seq_Q
seq_a[0] = floor(t)
#p_{k}序列
if i == 1:
seq_p.append(a0*seq_a[0]+1)
else:
seq_p[0] = seq_p[1]
seq_p[1] = seq_p[2]
seq_p[2] = seq_a[0]*seq_p[1]+seq_p[0]
#分解因式
if i%2 == 0 and is_square(seq_Q):
s = int(sqrt(seq_Q))
factor = [gcd(seq_p[1]-s,n),gcd(seq_p[1]+s,n)]
if factor[0] != 1 and factor[1] != 1:
print(f'第{i}项:{factor[0]},{factor[1]}')
break
# if i%1000 == 0:
# print(f'已运行到第{i}项')
i += 1
有特定特征
如果知道数的特征,就可以非常快速的进行分解。
代数群因子分解算法
0x1 \(p-1\)光滑,Pollard's p-1算法
原理
在自然数里找个\(s\),满足\(s=1\pmod p\),这就说明\(p\)试\((s-1)\)的一个因子,然后计算\(gcd(s-1,n)\)就好了。
实现
难题就在于怎么找到这个\(s\)。在不知道\(p\)的情况下,我们很难找到这个\(s\),不过伟大的费马会给出答案:
\[a^{p-1}\equiv1\pmod p
\]
所以我们要计算\(p-1\)(雾 虽然直接计算\(p-1\)很难,但是我们可以改写一下费马小定理:
\[a^k\equiv1\pmod p~~if~~(p-1)|k
\]
就这样,Pollard给出了算法。我们假设\(p-1\)有个因子\(B\),那么就一定有\((p-1)|B!\),同时我们令\(a=2\)方便计算。这样我们就得到了\(s=a^{B!}\)。
import math
def Pollard_p_1(n,B):
print('Pollard_(p-1) start !')
a=2
for i in range(1,B):
a=pow(a,i,n)
p=math.gcd(a-1,n)
if p!=1 and p!=n:
print('p=',p,'\nPollard_(p-1) finish !')
return p
print('Pollard_(p-1) failure !')
0x2 \(p+1\)光滑,Williams' p+1算法
前置知识
\(Lucas\)序列:
\[U_n(P,Q)=PU_{n-1}(P,Q)-QU_{n-2}(P,Q)\\
V_n(P,Q)=PV_{n-1}(P,Q)-QV_{n-2}(P,Q)\\
U_0(P,Q)=0, \ U_1(P,Q)=1\\
V_0(P,Q)=2, \ V_1(P,Q)=P
\]
当这个序列在有限域\(p\)内进行时,会有一些奇妙的结论。其中有个待会用到的:
\[若 p 是奇素数,且 p\nmid PQD,则 p\mid U_l(P,Q)\\
其中 D=P^2−4Q, l=p−(\frac{D}{p}), (\frac{D}{p})是勒让德符号
\]
第一步,保证\((\frac{D}{p})=-1\),这样\(l=p+1\)。与上个算法相同,我们能找到\((p+1)\mid B!\)这样的\(B\)。现在问题就在于\(p\mid U_l\),那么\(p\)是否整除\(U_{kl}\)?
用特征方程搞一搞:
\[数列特征方程为x^2-Px+Q=0\\
得a,b=\frac{P\pm\sqrt{D}}{2}\\
通项为U(n)=\frac{a^n-b^n}{\sqrt{D}}\\
\frac{U_{kl}}{U_L}=\frac{a^{kl}-b^{kl}}{a^l-b^l}=\frac{(a^l-b^l(\sum_{i=0}^{i=n-1}a^ib^{n-i-1}))}{a^l-b^l}
\]
现在我们找个\(B\),计算\(U_{B!}\)就能分解了。
这边借助矩阵快速幂进行加速:
\[ \begin{bmatrix}U_{i+1}\\U_{i}\end{bmatrix}=\begin{bmatrix}P&-Q\\1&0\end{bmatrix}\cdot\begin{bmatrix}U_1\\U_0\end{bmatrix}
\]
from Crypto.Util.number import *
import numpy as np
def Williams(n,A_list):
v=np.matrix([0,1])
for A in A_list:
L=np.matrix([[A,2],[1,0]])
for j in range(3000):
L=L^(j+1)
V=int((L*v)[0])
p=GCD(V,n)
if(p!=1):
q=n//p
return p,q
A_list = [5, 7, 9, 11, 13]
p,q=Williams(n,A_list)
print(f"p={p}\nq={q}")
0x3 Lenstra椭圆曲线因子分解法
费尔马因子分解法
奇奇怪怪的算法
还有一些奇奇怪怪的算法也能分解质因数。

浙公网安备 33010602011771号