概述
光滑数 (Smooth number):指可以分解为多个小素数乘积的正整数
当p是N 的因数,并且p−1是光滑数,可以考虑使用Pollard's p-1
算法来分解N
当p是N的因数,并且p+1是光滑数,可以考虑使用Williams's p+1
算法来分解N
这里只介绍pollard p-1算法
算法核心
假设存在素数p,p是合数n的因子,p-1可以被分解成多个小素数k1,k2,k3......kn<B(其中B是我们选取的一个上界)
p-1=k1*k2*k3...*kn
那么存在 p-1 | B!
由费马小定理可知:
因为p-1 | B!所以
所以
而我们的目的就是求出p
于是乎
代码实现:这里m取最简单的值:2
#脚本1
def Pollard(B, n):a = pow(2, math.factorial(B), n)return math.gcd(a-1, n)
math.factorial(B)是求B的阶乘
a = pow(2, math.factorial(B), n) 这里模n可以减小数值,加快计算,否则脚本执行会很慢很慢
#脚本2
m = 2
i = 2
while True:a = pow(m, i, n)p = gmpy2.gcd(a-1, n)if p != 1 and p != n:q = n // pprint("p=",p)print("q=",q)breaki += 1
这里没用上界B,而是不断用m乘i,构成阶乘,从而找到上界
案例
2024_newstar_crypto
from Crypto.Util.number import *
from random import choice
from enc import flagm = bytes_to_long(flag)
def get_primes(limit):primes = []is_prime = [True] * (limit + 1)for num in range(2, limit + 1):if is_prime[num]:primes.append(num)for multiple in range(num * num, limit + 1, num):is_prime[multiple] = Falsereturn primesdef get_Prime(bits):while True:n = 2while n.bit_length() < bits:n *= choice(primes)if isPrime(n + 1):return n + 1e = 65537
primes = get_primes(e)
p = get_Prime(512)
q = get_Prime(512)
n = p*q
c = pow(m,e,n)
print(f"n = {n}")
print(f"e = {e}")
print(f"c = {c}")
'''
n = 11039465757321779749699115271175512667139900174718736810369447320076323722255434292310358024561522508796910115450323496447022239437773990981536427837406218598107069494432101729405702532145398564394815485237091250665627736733029998539907483103936019387506766847901269370907583069348340970264589547521878184740704877
e = 65537
c = 999985242089285281573358992862050772171553905758195933815934618530062196165616033686130348967500088738894025554769544651219372069639483611911419044407380282591769389311004388591587725946534597210624224229109408954620531714696257219047380587652138116530227788392134058889161962899416080258311278619324733722515967
'''
这里的光滑数是p+1,但本质都是一样的
脚本代码
from Crypto.Util.number import *
from random import choice
from sympy import factorint
import math
import gmpy2n = 11039465757321779749699115271175512667139900174718736810369447320076323722255434292310358024561522508796910115450323496447022239437773990981536427837406218598107069494432101729405702532145398564394815485237091250665627736733029998539907483103936019387506766847901269370907583069348340970264589547521878184740704877
e = 65537
c = 999985242089285281573358992862050772171553905758195933815934618530062196165616033686130348967500088738894025554769544651219372069639483611911419044407380282591769389311004388591587725946534597210624224229109408954620531714696257219047380587652138116530227788392134058889161962899416080258311278619324733722515967def Pollard(B, n):a = pow(2, math.factorial(B),n)return math.gcd(a-1, n)
p=Pollard(e,n)
q=n//p
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)flag=pow(c,d,n)
print(long_to_bytes(flag))