已知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:

\[1 + \lfloor a/A \rfloor \leq k \leq \min(e,d),\quad 1 + \lfloor b/B \rfloor \]

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:

  1. 111111 (all 1's)
  2. -111111 (starts with -1 then all 1's)
  3. ***-111111 (some values ≠1,≠n-1, then -1, then 1's)
  4. ***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) 关系分解

  1. 计算 k = e×d-1 并分解为 2^t × r
  2. 随机尝试:选择随机数 g,计算 g^r mod N
  3. 迭代平方:最多 t 次平方运算,寻找非平凡平方根
  4. 计算 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\) 表示为:

\[k = 2^t \times r \]

其中 \(r\) 是奇数。

对于随机选择的基数 \(g\),计算:

\[y = g^r \mod N \]

然后通过连续平方运算寻找非平凡平方根,从而找到 \(N\) 的因子。

主要分解流程:

  1. 初始化:将 \(N\) 放入待分解栈中
  2. 循环处理:从栈中取出当前数 \(m\)
  3. 素性检测:如果 \(m\) 是素数,加入结果列表
  4. 三重分解策略
    • 优先使用 \(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秒:已知因子不大时
posted @ 2025-10-27 19:29  Mirai_haN  阅读(18)  评论(0)    收藏  举报