数学体操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椭圆曲线因子分解法

费尔马因子分解法

奇奇怪怪的算法

还有一些奇奇怪怪的算法也能分解质因数。

\(Pollard~rho\)算法

\(Dixon\)随机平方算法

posted @ 2023-08-06 19:37  络辰  阅读(415)  评论(0)    收藏  举报