已知N,e,d分解N的研究
已知N,e,d分解N
今天打2025强网拟态的密码题遇到了一个已知e,d,n分解n的问题,在到处看文章之后总结了一下板子。
网上大部分都是c语言或者java的解题脚本,python的比较少。
n有两个因子:
RSAwithknown_d/RSAwithknown_d.py at main · wang2000star/RSAwithknown_d
参考这个算法。
We have the following principles for factoring \(n = pq\) given \(e\) and \(d\):
Principle 1:
We suppose \(q < p < Lq\), actually \(L\) always is 2;
\(p + q > 2\sqrt{pq}\),
\(p + q = \sqrt{(p-q)^2 + 4pq} < \sqrt{pq(L+1)^2/L}\)
Let \(\phi = pq - (p+q) + 1\), \(k = (ed - 1)/\phi\),
\(\max(e,d) < \phi\), \(1 \leq k < \min(e,d)\)
Define:
- \(W = ed - 1\)
- \(a = (n + 1)W + \sqrt{4nW^2}\)
- \(A = (n - 1)^2\)
- \(L = 2\)
- \(b = L(n + 1)W + \frac{\sqrt{L^3(L+1)^2nW^2}}{2}\)
- \(B = L(n + 1)^2 - (L+1)^2n\)
So we have:
Principle 2:
Let \(k = ed - 1 = 2^s \cdot t\), where \(k\) is an even number, \(s \geq 1\), \(t \geq 1\).
Randomly select an integer \(g\) where \(1 < g < n-1\).
Case 1: If \(\gcd(g,n) \neq 1\), then \(p = \gcd(g,n)\) is a factor of \(n\).
Case 2: If \(\gcd(g,n) = 1\), for \(0 \leq i \leq s\), the values of \((g^t)^{2^i} \mod n\) fall into four categories:
- 111111 (all 1's)
- -111111 (starts with -1 then all 1's)
- ***-111111 (some values ≠1,≠n-1, then -1, then 1's)
- ***111111 (some values ≠1,≠n-1, then 1's)
For the first three categories, reselect \(g\).
For the fourth category, if \(x^2 \mod n = 1\), then \(n \mid (x+1)(x-1)\), \(1 \leq x \leq n-1\), \(-1 \leq x^2-1 \leq n(n-2)\).
If \(x \neq 1\) and \(x \neq n-1\), then:
- \(2 < x+1 < n\)
- \(0 < x-1 < n-2\)
- So \(1 \leq \gcd(x-1,n)\), \(\gcd(x+1,n) < n\)
Suppose \(\gcd(x-1,n) = 1\), then \(n \mid x+1\), contradiction; similarly, suppose \(\gcd(x+1,n) = 1\), then \(n \mid x-1\), contradiction.
The factors of \(n\) are only \(1\), \(p\), \(q\), \(n\), so \(\gcd(x-1,n) = p\) or \(q\) and \(\gcd(x+1,n) = p\) or \(q\).
exp:
import gmpy2,random
#the function to check if n is a perfect square
def is_perfect_square(n):
'''
If n is a perfect square it returns sqrt(n),
otherwise returns -1
'''
h = n & 0xF; #last hexadecimal "digit"
if h > 9:
return -1 # return immediately in 6 cases out of 16.
# Take advantage of Boolean short-circuit evaluation
if ( h != 2 and h != 3 and h != 5 and h != 6 and h != 7 and h != 8 ):
# take square root if you must
t = gmpy2.isqrt(n)
if t*t == n:
return t
else:
return -1
return -1
#the first method to factorize n with known e and d
def factor_pqRange(n, e, d):
"""
Pricinple: we suppose q<p<Lq, acutually L always be 2;
p+q>2sqrt(pq),p+q=sqrt((p-q)^2+4pq)<sqrt(pq(L+1)^2/L)
phi=pq-(p+q)+1,k=(ed-1)/phi,
max(e,d)<phi,1<=k<min(e,d)
so 1+a//A<=k<=min{e,d,1+b//B},where"//"denotes floor division.
In addition, it is easy to find a simple corollary, when ed <= 16*n^(3/2), a//A = b//B.
Specifically, when min(e,d) <= 16*n^(1/2), it is obvious that a//A = b//B.
"""
W = e*d - 1
a = (n + 1)*W + gmpy2.isqrt(4*n*W**2)
A = pow(n - 1,2)
L = 2
b = L*(n + 1)*W + int(gmpy2.sqrt(L**3*(L+1)^2*n*W**2)/2)
B = L*pow(n + 1,2) - (L+1)**2*n
kmin = 1 + a//A
ed_min = min(e,d)
if ed_min**2 <= 64*n | W**2<=64*n**3:
kmax = kmin
else:
kmax = min(ed_min - 1, 1 + b//B)
for k in range(kmin, kmax+1):#range is [kmin,kmax]
if W % k == 0:
phi = W // k
s = n - phi + 1
# check if the equation x^2 - s*x + n = 0
# has integer roots
discr = s*s - 4*n
if(discr>=0):
t = is_perfect_square(discr)
if t!=-1 and (s+t)%2==0:
#pq=n,pq-p-q+1=phi,所以p+q=n-phi+1=s,p-q=t,所以p=(s+t)/2,q=(s-t)/2,假设p>q的情况
return (s+t)//2,(s-t)//2
#the second method to factorize n with known e and d
def factor_pq(n, e, d):
"""
Factorizes the given RSA modulus (n) using the known private exponent (d) and public exponent (e).
Principle: Let k=ed-1=2^s*t, where k is an even number, s>=1, t>=1. Randomly select an integer g, 1<g<n-1.
Case 1: If gcd(g,n)!=1, then p=gcd(g,n) is a factor of n.
Case 2: If gcd(g,n)=1, for 0<=i<=s, the values of (g^t)^(2^i) mod n fall into four categories:
111111; -111111; ***-111111; ***111111, where * represents !=1 and !=n-1.
For the first three categories, reselect g.
For the fourth category, if x^2 mod n = 1, then n|(x+1)(x-1), 1<=x<=n-1, -1<=x^2-1<=n(n-2);
If x!=1 and x!=n-1, then 2<x+1<n, 0<x-1<n-2, so 1<=gcd(x-1,n), gcd(x+1,n)<n.
Suppose gcd(x-1,n)=1, then n|x+1, contradiction; similarly, suppose gcd(x+1,n)=1, then n|x-1, contradiction.
The factors of n are only 1, p, q, n, so gcd(x-1,n)=p or q and gcd(x+1,n)=p or q.
Args:
n (int): The RSA modulus.
e (int): The public exponent.
d (int): The private exponent.
Returns:
tuple: A tuple containing the factors of n.
"""
k = e*d - 1
t=k
while t % 2 == 0:
t = t // 2
while True:
g = random.randint(2, n-2)
gcd_gn = gmpy2.gcd(g, n)
if gcd_gn != 1:
p = gcd_gn
if pow(p,2) > n:
return (p, n//p)
return (n//p, p)
else:
x=pow(g,t,n)
if x==1 or x==n-1:
continue
else:
while True: # Will find y=-1 or 1 within s times
y=pow(x,2,n)
if y==1:
p = gmpy2.gcd(x-1, n)
if pow(p,2)>n:
return (p, n//p)
return (n//p, p)
if y==n-1:
break
x=y
if __name__ == "__main__":
n = 0xd231f2c194d3971821984dec9cf1ef58d538975f189045ef8a706f6165aab4929096f61a3eb7dd8021bf3fdc41fe3b3b0e4ecc579b4b5e7e035ffcc383436c9656533949881dca67c26d0e770e4bf62a09718dbabc2b40f2938f16327e347f187485aa48b044432e82f5371c08f6e0bbde46c713859aec715e2a2ca66574f3eb
e = 0x5b5961921a49e3089262761e89629ab6dff2da1504a0e5eba1bb7b20d63c785a013fd6d9e021c01baf1b23830954d488041b92bca2fe2c92e3373dedd7e625da11275f6f18ee4aef336d0637505545f70f805902ddbacb21bb8276d34a0f6dfe37ede87dd95bb1494dbb5763639ba3984240f1178e32aa36ee3c5fcc8115dde5
d = 0x31df315ae64639876342f0ce3367a436ad9b92201a450b0d8b1465786a53a5e01bd70025
p,q = factor_pqRange(n,e,d)
if p*q == n:
print("sucess!")
print("p:",hex(p))
print("q:",hex(q))
else:
print("failed")
n有三个因子
第一阶段:利用 (e,d) 关系分解
- 计算 k = e×d-1 并分解为
2^t × r - 随机尝试:选择随机数 g,计算 g^r mod N
- 迭代平方:最多 t 次平方运算,寻找非平凡平方根
- 计算 GCD:找到因子后递归分解
第二阶段:回退方案
如果第一阶段失败,使用:
- Pollard's Rho 算法:概率性分解方法
- Miller-Rabin 测试:验证素性
exp:
e = 271264973728317298627822473902975461834475616151421882685140849409171660245987005602120200976835072966082573357282000859946014645129524701781302678299643424924092704444611429422064341444927220441684375194952864825982915148126084102832224731498348832396834993134927447743362540828447462072582023959357845229307404791804881057335208287771899121154533179273274029972648764343120454360366227609296867085751393693129946684282269737380796082741762647814800935844443493
d = 79707249059210800427586261608616662408613108106616463837006013556788454508274558925787023296092333364088239266520329780878389357
N = 729626364576206469704240917876675932841677846807662743683194531189219993605123671836962855605283722577718230552963049472251011326675202612492908848548419883361685662678347011887752523869081347313358470192291106167923273619672010347904232948623232956703976722596246251219832472749781700661621717970912452690860710243752051416797956410009096107757901714990018414837758557784033898837218196380413347278999394220278929595840196278059116531409774355756772349502091527
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Recover prime factors of N (possibly >2 primes) given (e,d,N)
# Strategy: use k = e*d - 1 = 2^t * r and the classical algorithm that
# finds non-trivial gcd(g^((2^j) r) - 1, N) for random g.
# When a nontrivial factor is found, recursively factor the cofactor.
# Includes Pollard-Rho as fallback for factoring subparts.
import random, math, time
from typing import List
# ---------- Miller-Rabin primality test ----------
def is_probable_prime(n: int, witnesses=[2,3,5,7,11,13,17,19,23,29,31]):
if n < 2:
return False
small = [2,3,5,7,11,13,17,19,23,29,31]
for p in small:
if n % p == 0:
return n == p
# write n-1 = d * 2^s
d = n - 1
s = 0
while d % 2 == 0:
s += 1
d //= 2
def check(a, s, d, n):
x = pow(a, d, n)
if x == 1 or x == n - 1:
return True
for _ in range(s - 1):
x = (x * x) % n
if x == n - 1:
return True
return False
for a in witnesses:
if a % n == 0:
continue
if not check(a, s, d, n):
return False
return True
# ---------- Pollard-Rho (for factoring cofactors) ----------
def pollard_rho(n: int, max_iters=200000):
if n % 2 == 0:
return 2
if is_probable_prime(n):
return n
while True:
x = random.randrange(2, n-1)
y = x
c = random.randrange(1, n-1)
d = 1
for _ in range(max_iters):
x = (x*x + c) % n
y = (y*y + c) % n
y = (y*y + c) % n
d = math.gcd(abs(x-y), n)
if d == 1:
continue
if d == n:
break
return d
# try new random parameters
def factor_pollard_recursive(n: int) -> List[int]:
"""Return list of prime factors (may include repeats)."""
if n == 1:
return []
if is_probable_prime(n):
return [n]
d = pollard_rho(n)
if d is None or d == n:
# give up, return n as composite fallback
return [n]
left = factor_pollard_recursive(d)
right = factor_pollard_recursive(n // d)
return left + right
# ---------- Core: find a nontrivial factor using k = ed - 1 ----------
def find_nontrivial_factor_from_ed(e: int, d: int, N: int, tries: int = 200) -> int:
"""
Try to find a nontrivial factor of N using k = e*d - 1 = 2^t * r.
Returns a factor f with 1 < f < N or None if not found within tries.
"""
k = e * d - 1
if k <= 0:
return None
# factor out powers of two: k = 2^t * r with r odd
r = k
t = 0
while r % 2 == 0:
r //= 2
t += 1
if t == 0:
# k is odd (rare) - algorithm typically expects t >= 1; still can try r=k
r = k
t = 0
for attempt in range(tries):
g = random.randrange(2, N-1)
y = pow(g, r, N)
if y == 1 or y == N - 1:
continue
# iterate squaring up to t-1 times
for j in range(t):
x = pow(y, 2, N)
# if we hit 1, then previous y is nontrivial square root of 1 mod some prime factors
if x == 1:
factor = math.gcd(y - 1, N)
if 1 < factor < N:
return factor
else:
# sometimes gcd is trivial; break and try another g
break
if x == N - 1:
# this g didn't work, go next random g
break
y = x
# else continue tries
return None
# ---------- Recursively factor N using the above finder ----------
def factor_N_from_ed(e: int, d: int, N: int, tries_per_round: int = 200, pollard_timeout_seconds: int = 60):
"""
Attempts to fully factor N (multi-prime allowed) using (e,d,N).
Returns sorted list of prime factors (best-effort).
"""
to_factor = [N]
result = []
start_time = time.time()
while to_factor:
m = to_factor.pop()
if m == 1:
continue
if is_probable_prime(m):
result.append(m)
continue
# try to get a factor from ED relation
f = find_nontrivial_factor_from_ed(e, d, m, tries=tries_per_round)
if f and 1 < f < m:
co = m // f
# push both parts for further factoring
to_factor.append(f)
to_factor.append(co)
continue
# fallback: try pollard-rho on m
# run pollard a few times for a limited total time
elapsed = time.time() - start_time
if elapsed < pollard_timeout_seconds:
d2 = pollard_rho(m)
if d2 and 1 < d2 < m:
to_factor.append(d2)
to_factor.append(m // d2)
continue
# if cannot factor, return what we have plus this composite leftover
# try to factor m further with recursive pollard (may take longer)
more = factor_pollard_recursive(m)
# if recursion returns composite m itself, include and break
prod = 1
for x in more:
prod *= x
if prod == m:
result.extend(more)
else:
# expand into to_factor stack
for part in more:
to_factor.append(part)
result = sorted(result)
# final verification: multiply to check equals original N (only if original passed)
return result
# ---------- Example usage ----------
if __name__ == "__main__":
e = 271264973728317298627822473902975461834475616151421882685140849409171660245987005602120200976835072966082573357282000859946014645129524701781302678299643424924092704444611429422064341444927220441684375194952864825982915148126084102832224731498348832396834993134927447743362540828447462072582023959357845229307404791804881057335208287771899121154533179273274029972648764343120454360366227609296867085751393693129946684282269737380796082741762647814800935844443493
d = 79707249059210800427586261608616662408613108106616463837006013556788454508274558925787023296092333364088239266520329780878389357
N = 729626364576206469704240917876675932841677846807662743683194531189219993605123671836962855605283722577718230552963049472251011326675202612492908848548419883361685662678347011887752523869081347313358470192291106167923273619672010347904232948623232956703976722596246251219832472749781700661621717970912452690860710243752051416797956410009096107757901714990018414837758557784033898837218196380413347278999394220278929595840196278059116531409774355756772349502091527
import sys
if len(sys.argv) >= 4:
e = int(sys.argv[1])
d = int(sys.argv[2])
N = int(sys.argv[3])
# else use the values in outer scope if set
print("N bitlen:", N.bit_length(), "k bitlen:", (e*d-1).bit_length())
t0 = time.time()
factors = factor_N_from_ed(e, d, N, tries_per_round=400, pollard_timeout_seconds=120)
t1 = time.time()
print("Found factors (possibly with multiplicity):")
for f in factors:
print(f)
print("Elapsed:", t1 - t0, "seconds")
n不知道有多少因子
整了个板子,可以直接套
设 \(k = e \times d - 1\),则 \(k\) 是欧拉函数 \(\phi(N)\) 的倍数。将 \(k\) 表示为:
其中 \(r\) 是奇数。
对于随机选择的基数 \(g\),计算:
然后通过连续平方运算寻找非平凡平方根,从而找到 \(N\) 的因子。
主要分解流程:
- 初始化:将 \(N\) 放入待分解栈中
- 循环处理:从栈中取出当前数 \(m\)
- 素性检测:如果 \(m\) 是素数,加入结果列表
- 三重分解策略:
- 优先使用 \(e,d\) 关系分解
- 其次使用 Pollard Rho 算法
- 最后使用递归 Pollard Rho
exp1:
import random
import math
import time
import sys
def is_prime(n, tests=20):
"""
米勒-拉宾素性测试
n: 要测试的数
tests: 测试次数,次数越多准确性越高
"""
if n < 2:
return False
# 小素数快速检测
small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
for p in small_primes:
if n == p:
return True
if n % p == 0:
return False
# 将n-1写成d*2^s的形式
d = n - 1
s = 0
while d % 2 == 0:
s += 1
d //= 2
def witness_check(a, s, d, n):
"""检查a是否为n的见证数"""
x = pow(a, d, n)
if x == 1 or x == n - 1:
return True
for _ in range(s - 1):
x = (x * x) % n
if x == n - 1:
return True
return False
# 进行多次测试
for _ in range(tests):
a = random.randrange(2, n - 2)
if not witness_check(a, s, d, n):
return False
return True
def rho_factor(n, max_iters=100000):
"""
Pollard Rho算法分解因数
n: 要分解的数
max_iters: 最大迭代次数
"""
if n % 2 == 0:
return 2
if is_prime(n):
return n
# 使用多项式f(x) = (x^2 + c) mod n
x = random.randrange(2, n - 1)
y = x
c = random.randrange(1, n - 1)
d = 1
for i in range(max_iters):
x = (x * x + c) % n
y = (y * y + c) % n
y = (y * y + c) % n
d = math.gcd(abs(x - y), n)
if d == 1:
continue
if d == n:
# 失败,重新选择参数
break
return d
return None
def recursive_rho_factor(n):
"""
递归使用Pollard Rho分解因数
返回所有素因子列表
"""
if n == 1:
return []
if is_prime(n):
return [n]
# 尝试分解
d = rho_factor(n)
if d is None or d == n:
return [n] # 无法分解
# 递归分解两个因子
factors1 = recursive_rho_factor(d)
factors2 = recursive_rho_factor(n // d)
return factors1 + factors2
def find_factor_from_ed(e, d, N, tries=500):
"""
利用RSA的e,d来分解N
e,d: RSA的公钥指数和私钥指数
N: RSA模数
tries: 尝试次数
"""
k = e * d - 1 # k是φ(N)的倍数
if k <= 0:
return None
# 将k写成k = 2^t * r的形式,其中r是奇数
r = k
t = 0
while r % 2 == 0:
r //= 2
t += 1
# 如果t=0,说明k是奇数,这种情况很少见
if t == 0:
r = k
t = 0
for attempt in range(tries):
# 随机选择基数g
g = random.randrange(2, N - 1)
# 计算g^r mod N
y = pow(g, r, N)
# 如果y=1或y=N-1,这个g没用
if y == 1 or y == N - 1:
continue
# 逐步平方,寻找非平凡平方根
for j in range(1, t + 1):
x = pow(y, 2, N) # 平方
if x == 1:
# 找到了非平凡平方根
factor = math.gcd(y - 1, N)
if 1 < factor < N:
return factor
else:
break
if x == N - 1:
# 这个g无法提供有用信息
break
y = x # 继续下一轮
return None
def factorize_rsa_modulus(e, d, N, ed_tries=500, rho_timeout=120):
"""
主分解函数:利用(e,d,N)分解RSA模数
e,d,N: RSA参数
ed_tries: 使用e,d方法的尝试次数
rho_timeout: Pollard Rho超时时间(秒)
"""
# 使用栈来处理待分解的数
stack = [N]
prime_factors = []
start_time = time.time()
while stack:
current = stack.pop()
if current == 1:
continue
# 如果是素数,直接加入结果
if is_prime(current):
prime_factors.append(current)
continue
# 方法1: 使用e,d关系分解
factor = find_factor_from_ed(e, d, current, ed_tries)
if factor and 1 < factor < current:
cofactor = current // factor
stack.append(factor)
stack.append(cofactor)
continue
# 方法2: 使用Pollard Rho分解
elapsed = time.time() - start_time
if elapsed < rho_timeout:
rho_factor_result = rho_factor(current)
if rho_factor_result and 1 < rho_factor_result < current:
stack.append(rho_factor_result)
stack.append(current // rho_factor_result)
continue
# 方法3: 递归Pollard Rho作为最后手段
rho_factors = recursive_rho_factor(current)
product = 1
for f in rho_factors:
product *= f
if product == current:
# 成功分解
for f in rho_factors:
if is_prime(f):
prime_factors.append(f)
else:
stack.append(f)
else:
# 分解失败,将剩余部分当作素数处理
prime_factors.append(current)
# 排序并返回结果
prime_factors.sort()
return prime_factors
def verify_factorization(factors, N):
"""验证分解结果的正确性"""
product = 1
for f in factors:
if not is_prime(f):
print(f"警告: {f} 可能不是素数")
product *= f
if product == N:
print("✓ 分解验证成功")
return True
else:
print("✗ 分解验证失败")
return False
if __name__ == "__main__":
# 默认参数(你的大数)
N = 3017482617205653324174047381971155912925723635753881880965783444218202443526598692186168553766617493388499734207147020349751762566409784209984644675778597260344544460290008418942655024374634016834992926350535285565714700270003046880031760292672079111749210854849808936785324081858463242122869504348662247513655946894146284246174391047802024000617524798285311721901504389716434353716054762461207726615161452265396510378315471561742019581222139336798920403435662221605743643953424519022029936192100503426591396474519222533514044559798700459876389926919539986817975180527501227788009344816760148586572258928715850185745449078183190345702049148514977139665273126866301796341878261160871738248420337441399045673843551942656783330879428861599681236308363517679984644668967053881816948107835386844562444207677826907180386414617501142391837621131896644587781996841954847710580967379890127675264092541364947951793577168269520247623952957117015831614258428957329053180434341536146909102554485072760473671445813328359443379693725285029490055921746564096991015341089653189126859435706753396168640515301989491267121090488805774118833847035277220297132982474541181177003201901835807201341708157014410451786327230766616504781342741998360201644374507070744997189024044058412497691060091677000762453264468055319190573799563875433757594954401643798419126884127199826993927460691681272970413283283226961119
d = 8762470729622240750398619904557657492126517460922183753973391319073521239487035750258930324701444339676176508952918375065169110365443504888106372135417341918035581904970257720939357852775360688275272869336018787213917626935344746344353975771470840311858819413257891670030205442063037876736178991582346348265681963109119852360464722656223440078566758840769434343719257935504936874815624216981956160443873569069151339279435669663194379032744712105780872997115914376395616168586137083987294003490436991880833741081811019508640746074697761584820197389280420989868165596985012695973227504729879029828709111007117525669699031670992257843415384962790684462843828799878426491813598091498621129231878053186450839320828865349784272850522117631855704165856156299371116839767245845386770502743184957874312971098592619237479575208067041318209952615061790268175037378423582120554480473718683177381185829003152670730828456579674147111368651653869052705929388556156647381545304958067920175471274585047399432417059363191810704262456450019852821977865204892808094261401544939012008033405658666722584921235698526400378374310690098060864326679655362401147869725834536467393071814384505669588697527450013468226467620505504433
e = 2335563752621422268034981786831753728931046586840885273141770447518344849787580593907151514118654523554031040397380586053300808452372510112374862258841716758944718730044877643399291174878855800911808897200720133059879233127387882201676506758696657708807067272510409225116174428727710863627926757553193816433692495467091393237685860431973676013737903717744532637210192734940170662369832745928038343780180373134043100475836417355117457983118196814359458091094440574909641045863813155082472850255791448381323107036746425611633051480870140388978514849628349266151518601147734233142055333512750384687760947541162666775973120499470451282291375772290597251714294897697014332099732437891821624829435622681974900294331170650586828818979646725659487712477686472722556465524074813608698788068387223609594400639096291785618420924966397251106183959030778200062167312200616529289218868846058612395835498673633737696094994615029186938549680598761773294696114626592027824553438544391522512878859049152896720228566954926199533902390184689504032987021606554252110905834442227823661355403045166254532441877061569837756851520272435044128707991985133357602108733808280836768895337023847427919819947060776928148041128684623598118160822064592816879043181194828249832106443250341710428729417679378968581381015318670025183048686454073497678004078134553535178718834841090576181645597155824138765966645086919753297
print("RSA参数信息:")
print(f"N 位数: {N.bit_length()}")
print(f"k = e*d-1 位数: {(e * d - 1).bit_length()}")
print(f"e 位数: {e.bit_length()}")
print(f"d 位数: {d.bit_length()}")
print("-" * 50)
print("开始分解...")
start_time = time.time()
factors = factorize_rsa_modulus(
e, d, N,
ed_tries=800, # 增加尝试次数
rho_timeout=180 # 延长超时时间
)
end_time = time.time()
print("\n分解结果:")
print(f"找到 {len(factors)} 个因子:")
for i, factor in enumerate(factors, 1):
print(f"因子 {i}: {factor} (素数: {is_prime(factor)})")
print(f"\n耗时: {end_time - start_time:.2f} 秒")
# 验证结果
print("\n验证分解结果:")
verify_factorization(factors, N)
# 显示因子关系
if len(factors) >= 2:
print(f"\n因子关系: N = {' * '.join(map(str, factors))}")
exp2详细输出版本
import random
import math
import time
import sys
def is_prime(n, tests=20):
"""
米勒-拉宾素性测试
n: 要测试的数
tests: 测试次数,次数越多准确性越高
"""
if n < 2:
return False
# 小素数快速检测
small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
for p in small_primes:
if n == p:
return True
if n % p == 0:
return False
# 将n-1写成d*2^s的形式
d = n - 1
s = 0
while d % 2 == 0:
s += 1
d //= 2
def witness_check(a, s, d, n):
"""检查a是否为n的见证数"""
x = pow(a, d, n)
if x == 1 or x == n - 1:
return True
for _ in range(s - 1):
x = (x * x) % n
if x == n - 1:
return True
return False
# 进行多次测试
for _ in range(tests):
a = random.randrange(2, n - 2)
if not witness_check(a, s, d, n):
return False
return True
def rho_factor(n, max_iters=100000, verbose=False):
"""
Pollard Rho算法分解因数
n: 要分解的数
max_iters: 最大迭代次数
verbose: 是否输出详细过程
"""
if n % 2 == 0:
if verbose:
print(f" [Pollard Rho] 发现偶数因子: 2")
return 2
if is_prime(n):
if verbose:
print(f" [Pollard Rho] {n} 是素数")
return n
if verbose:
print(f" [Pollard Rho] 开始分解 {n} (位数: {n.bit_length()})")
# 使用多项式f(x) = (x^2 + c) mod n
x = random.randrange(2, n - 1)
y = x
c = random.randrange(1, n - 1)
d = 1
for i in range(max_iters):
x = (x * x + c) % n
y = (y * y + c) % n
y = (y * y + c) % n
d = math.gcd(abs(x - y), n)
if d == 1:
continue
if d == n:
if verbose:
print(f" [Pollard Rho] 第{i}次迭代: 找到平凡因子 {d}")
break
if verbose:
print(f" [Pollard Rho] 第{i}次迭代: 找到因子 {d}")
return d
if verbose:
print(f" [Pollard Rho] 未能分解 {n}")
return None
def recursive_rho_factor(n, depth=0, verbose=False):
"""
递归使用Pollard Rho分解因数
返回所有素因子列表
"""
indent = " " * depth
if n == 1:
return []
if is_prime(n):
if verbose:
print(f"{indent}[递归Rho] {n} 是素数")
return [n]
if verbose:
print(f"{indent}[递归Rho] 开始分解 {n} (位数: {n.bit_length()})")
# 尝试分解
d = rho_factor(n, verbose=verbose)
if d is None or d == n:
if verbose:
print(f"{indent}[递归Rho] 无法分解 {n}")
return [n]
if verbose:
print(f"{indent}[递归Rho] 成功分解: {n} = {d} * {n // d}")
# 递归分解两个因子
factors1 = recursive_rho_factor(d, depth + 1, verbose)
factors2 = recursive_rho_factor(n // d, depth + 1, verbose)
return factors1 + factors2
def find_factor_from_ed(e, d, N, tries=500, verbose=False):
"""
利用RSA的e,d来分解N
e,d: RSA的公钥指数和私钥指数
N: RSA模数
tries: 尝试次数
verbose: 是否输出详细过程
"""
k = e * d - 1 # k是φ(N)的倍数
if k <= 0:
return None
if verbose:
print(f"[e,d方法] k = e*d-1 = {k}")
print(f"[e,d方法] k的位数: {k.bit_length()}")
# 将k写成k = 2^t * r的形式,其中r是奇数
r = k
t = 0
while r % 2 == 0:
r //= 2
t += 1
if verbose:
print(f"[e,d方法] k = 2^{t} * {r}")
print(f"[e,d方法] 开始尝试 {tries} 次随机基数...")
# 如果t=0,说明k是奇数,这种情况很少见
if t == 0:
r = k
t = 0
if verbose:
print("[e,d方法] 警告: k是奇数,这可能影响分解效果")
for attempt in range(tries):
if verbose and attempt % 100 == 0:
print(f"[e,d方法] 第{attempt}次尝试...")
# 随机选择基数g
g = random.randrange(2, N - 1)
# 计算g^r mod N
y = pow(g, r, N)
# 如果y=1或y=N-1,这个g没用
if y == 1 or y == N - 1:
continue
# 逐步平方,寻找非平凡平方根
for j in range(1, t + 1):
x = pow(y, 2, N) # 平方
if x == 1:
# 找到了非平凡平方根
factor = math.gcd(y - 1, N)
if 1 < factor < N:
if verbose:
print(f"[e,d方法] 成功! 在第{attempt}次尝试找到因子: {factor}")
print(f"[e,d方法] 分解: {N} = {factor} * {N // factor}")
return factor
else:
break
if x == N - 1:
# 这个g无法提供有用信息
break
y = x # 继续下一轮
if verbose:
print(f"[e,d方法] 在{tries}次尝试后未找到因子")
return None
def factorize_rsa_modulus(e, d, N, ed_tries=500, rho_timeout=120, verbose=True):
"""
主分解函数:利用(e,d,N)分解RSA模数
e,d,N: RSA参数
ed_tries: 使用e,d方法的尝试次数
rho_timeout: Pollard Rho超时时间(秒)
verbose: 是否输出详细过程
"""
if verbose:
print("=" * 60)
print("开始RSA模数分解过程")
print("=" * 60)
# 使用栈来处理待分解的数
stack = [N]
prime_factors = []
start_time = time.time()
step = 0
while stack:
step += 1
current = stack.pop()
if verbose:
print(f"\n步骤 {step}: 处理数 {current} (位数: {current.bit_length()})")
if current == 1:
if verbose:
print(" 跳过: 当前数为1")
continue
# 如果是素数,直接加入结果
if is_prime(current):
if verbose:
print(f" ✓ 发现素数因子: {current}")
prime_factors.append(current)
continue
if verbose:
print(f" {current} 是合数,尝试分解...")
# 方法1: 使用e,d关系分解
if verbose:
print(" 尝试方法1: e,d关系分解")
factor = find_factor_from_ed(e, d, current, ed_tries, verbose=verbose)
if factor and 1 < factor < current:
cofactor = current // factor
if verbose:
print(f" ✓ e,d方法成功分解:")
print(f" {current} = {factor} * {cofactor}")
stack.append(factor)
stack.append(cofactor)
continue
# 方法2: 使用Pollard Rho分解
elapsed = time.time() - start_time
if elapsed < rho_timeout:
if verbose:
print(" 尝试方法2: Pollard Rho分解")
rho_factor_result = rho_factor(current, verbose=verbose)
if rho_factor_result and 1 < rho_factor_result < current:
cofactor = current // rho_factor_result
if verbose:
print(f" ✓ Pollard Rho成功分解:")
print(f" {current} = {rho_factor_result} * {cofactor}")
stack.append(rho_factor_result)
stack.append(cofactor)
continue
else:
if verbose:
print(" Pollard Rho超时,跳过")
# 方法3: 递归Pollard Rho作为最后手段
if verbose:
print(" 尝试方法3: 递归Pollard Rho")
rho_factors = recursive_rho_factor(current, verbose=verbose)
product = 1
for f in rho_factors:
product *= f
if product == current:
# 成功分解
if verbose:
print(f" ✓ 递归Pollard Rho成功分解为 {len(rho_factors)} 个因子")
for f in rho_factors:
if is_prime(f):
prime_factors.append(f)
if verbose:
print(f" → 素数因子: {f}")
else:
stack.append(f)
if verbose:
print(f" → 合数因子(重新入栈): {f}")
else:
# 分解失败,将剩余部分当作素数处理
if verbose:
print(f" ✗ 所有方法都失败,将 {current} 当作素数处理")
prime_factors.append(current)
# 排序并返回结果
prime_factors.sort()
if verbose:
print("\n" + "=" * 60)
print("分解完成!")
print("=" * 60)
return prime_factors
def verify_factorization(factors, N):
"""验证分解结果的正确性"""
print("\n" + "=" * 60)
print("验证分解结果")
print("=" * 60)
product = 1
for i, f in enumerate(factors, 1):
is_prime_flag = is_prime(f)
print(f"因子 {i}: {f}")
print(f" 位数: {f.bit_length()}, 素数: {is_prime_flag}")
if not is_prime_flag:
print(f" 警告: {f} 可能不是素数!")
product *= f
print(f"\n乘积验证: {' * '.join(map(str, factors))}")
print(f"计算结果: {product}")
print(f"原始模数: {N}")
if product == N:
print("✓ 分解验证成功")
return True
else:
print("✗ 分解验证失败")
return False
if __name__ == "__main__":
# 默认参数(你的大数)
N = 793633945741339423985729893068677400644570560995125048651979994039440725165213404687256380062046109788111281436660851215054751512643942274754458246146268546510555874104567679009025906593902156233395080166398545756713436933707998962100110303336378997723707686695911404127437567747229713840585402903423824601836223746470492792400884689717709816293332972662443476952986398465333918199936233156738068307032896778411784349386539441613220910965431014216090996608967537231649089998150831207853109505157929110293719447231759748915025776476221572649517568388558896311220946916012303276151623228907139377917987161237341716737999207815607008642142848843705500049558666691825763979350922385931394405796793253534181336857588147955947101278592998587373862765042266007866130127754832291970079614623447235083849761815795649289168302183474891031533352945540173281505437054941963871980160384954482487344193924501746304441008461956164604724387547460269222969942707501569146060420310413325111867538792116871154037945665270413606301235434270084332525414492928178431538185537723618253260526521958977689312228193040205722162095108051949547578996908491317740845780555416884632493606361238979299047477287934280619482766867986819204149544346828229812932962941742297643505761493534940209598558364715303649039646908247207305900635825397608734457983127708836541337691220521592991784984691234424878829209781927677096062473427094045237729715626208301699064170695694538984893505649827938631325142542872381873413238592499119890125931841192087394670037559582366342477500396792820573984952883827334624274636229335655407448532566095818707885696257763826032975187777610640777387207641554708501026903300408271751009943675847839880838365040838575737278480399788785332504269812014700732335781527637736385356506673129095170405000516629968600547486404294333119129832018363215497517791728725268291969020689095106796002478535397733299149560493153140566547175184368739867481483963934181199870334037423879210070150882788491627990853752572197968186539440606482200589552035349027147432885322130402315186125244875352911227638124509300679051489317156701347171753414098369579686054508687303227982129994560432413297837917483021059967485743005579117532170088537773423037630207964265431798180863273328424997119064044592130865862934653848545443071563270380133452524695123713802460841424728254533186874526021992187044442208230915454324006980601277858720974118989261928325365248558914471726179511076176046694616238733436253860819925984664188825958344000853775760843779373092988991840421076751044978470825210422736722973556474216258188490537852592480769890400843022335856706004470494632457594622918836516123006892707398934144575340977385123784194441728775418694122131
e = 620872399199856838383655695271451753468789166430581729114100401985258752704850573687685343260728770237945974829615424879242347441829095772732578902688043205630856380126510465089991747011865930104932584360368973086911580357239558632882469862684080601276920943682504241550207166666858247123339893467353134797969955391536909885423176584266066455583300476546017419209926052212071417638822508929122006267164903937941589316698682717434686793842123028891732844570186384217908349811132558270760921782228545966338542710804901234697764450070996274572563729976161847023004763375673305413600383596193534923839746252020544357004101525422047968395552164420952067595798985841654561572564178739362703564202057078445851622437762773706957371527144222849894918702392203411952094770498350973612512708389497653201357217924338265189893239442649187906190150012460736238995083030781568879068522542423207734161452203313359759893
d = 347506727381703568109739775250686676150363209728643768353355736843105295985380296683546311405961215192922018728683940844904669015274326680130828973073111245421008896215215156847556142230792050163040849663859513296775127348359813080385993756712693450986410308379098938932626935192204062639045801454457045648353564788244065950864996315952806664972895882811185465214953662117678173021451161937730994667985273816099568509695178327730441706681459772946652906429791416215250610745269080948026399974317052875576104137660670645792133433329540803261793611437215914867012691091893900971917950103487135667922505493018123829947406688143024414173785129627426563325341753082022587716592330598024331598854495594976437332564645835627334389307851399235751795375621679921873088495122223154475697485093721020754044493155790697525602687652097369784149053009757478867319376608781568408107080030802899747018190508109111028529108540645882257748756369596239055857542761302706759753229251049172896484027472393080247858386572233773642658473599016984813073421833870739953548562370867318417606685120461772674770706418934805222539593719523336622692651234601805035996407329369065131186998357430213730763317027627370544698368357313417220400898185256411731123756091393668004196101181903385567883719777130402959977699245397280298771226882374622087779343789057417028509866869486890804908198597459257599568578502705475138284783106064597918315827962632946797587327479223449241140669722116843876926928576638759100817911000400892708003707605318930659195794149060761498351210468356211540509302439389288286390382936952504642106482726566476587689527985901981106612891006617684586689765559425071520208655171459134811759631703038984061109992883448572135309972859804573717006744938829285601161106436275249442766020293100636617001979774542827517096860326747675213733368530048693643926875625721258656675654661902916978008611234272442696882499919372735314138517397578140968563714609203463136623955355657280549828073441734212670824347726305688554440038874424508566468542446049323046733017648295081925080547086703507172664691827686341523807795577350304647304198340261590330962228768482549560528240856444087575681422360625245534870184000195287153074034051230856319730325623176443029491721655540767066467685052725379090582612491492252409017304237816353707886972066463530733289022292101337588311171266512381861006614445218685233097720496538655201624357586089406510858440691871501462685637509489663096994746277122619597882099496350265645816106279052388263072250693375269167342965517355810721828066782799881908536220558388519800356020599497514803606182198323778578544427947447199070982803648839212095477973555598209399451731158348515885140161124821174937961656061
print("RSA参数信息:")
print(f"N 位数: {N.bit_length()}")
print(f"k = e*d-1 位数: {(e * d - 1).bit_length()}")
print(f"e 位数: {e.bit_length()}")
print(f"d 位数: {d.bit_length()}")
print("-" * 60)
print("开始分解...")
start_time = time.time()
# 设置verbose=True来显示详细分解过程
factors = factorize_rsa_modulus(
e, d, N,
ed_tries=800,
rho_timeout=180,
verbose=True # 设置为True显示详细过程
)
end_time = time.time()
print(f"\n总耗时: {end_time - start_time:.2f} 秒")
# 验证结果
verify_factorization(factors, N)
# 显示因子关系
if len(factors) >= 2:
print(f"\n最终因子关系: N = {' * '.join(map(str, factors))}")
参数选择建议
| 参数类别 | 参数名称 | 默认值 | 提高值及适用情况 | 降低值及适用情况 |
|---|---|---|---|---|
| 素性测试参数 | tests |
20次 | 50-100次:当怀疑有伪素数时 | 5-10次:追求速度,可接受小概率错误 |
| e,d分解参数 | ed_tries |
500-800次 | 1000-2000次:当k=e*d-1的2的幂次较低时 | 100-200次:当k有很高的2的幂次时 |
| Pollard Rho参数 | max_iters |
10万次 | 50-100万次:分解大素数因子时 | 1-5万次:当因子较小时 |
| 超时控制 | rho_timeout |
120-180秒 | 300-600秒:处理超大模数时 | 30-60秒:已知因子不大时 |

浙公网安备 33010602011771号