p-1光滑攻击

题目:

from Crypto.Util.number import *
from random import choice

flag = b'NSSCTF{******}'

def getMyPrime(nbits):
    while True:
        p = 1
        while p.bit_length() <= nbits:
            p *= choice(sieve_base)
        
        if isPrime(p+1):
            return p+1

p = getMyPrime(256)
q = getMyPrime(256)

n = p*q
e = 65537
m = bytes_to_long(flag)

c = pow(m, e, n)

print(f'n = {n}')
print(f'e = {e}')
print(f'c = {c}')

'''
n = 53763529836257082401813045869248978487210852880716446938539970599235060144454914000042178896730979463959004404421520555831136502171902051936080825853063287829
e = 65537
c = 50368170865606429432907125510556310647510431461588875539696416879298699197677994843344925466156992948241894107250131926237473102312181031875514294014181272618
'''

解题思路:

  • 在本题中,素数来自于getMyPrime函数,我们分析会发现,它的功能的从sieve_base中随机选取数字进行相乘,直到得到足够多的位数为止,最后还要判断如果p+1不是一个素数则重复上述过程
  • 简而言之,我们将会得到这样一个素数p=q1q2…qm+1
  • 根据Pollard的p-1算法得到关系gcd(M,n)=p,也就是说如果我们能够得到B_,_那么便可以通过求解和n的公因数得到n的素因子
  • M=t⋅(p−1),根据费马小定理我们有:

from gmpy2 import *
a = 2
m = 2
while True:
    a = powmod(a, m, n)
    p = gcd(a-1, n)
    if p != 1 and p != n:
        break
    m += 1
q = n // p

知识拓展:

光滑数(Smooth number):指可以分解为小素数乘积的正整数

当p是N的因数,并且p−1是光滑数,可以考虑使用Pollard的p-1算法来分解N

当p是N的因数,并且p+1是光滑数,可以考虑使用Williams的p+1算法来分解N

解答:

from Crypto.Util.number import *
from gmpy2 import *

n = 53763529836257082401813045869248978487210852880716446938539970599235060144454914000042178896730979463959004404421520555831136502171902051936080825853063287829
e = 65537
c = 50368170865606429432907125510556310647510431461588875539696416879298699197677994843344925466156992948241894107250131926237473102312181031875514294014181272618

a = 2
m = 2
while True:
    a = powmod(a, m, n)
    p = gcd(a-1, n)
    if p != 1 and p != n:
        break
    m += 1

q = n // p

phi = (p-1)*(q-1)
d = invert(e, phi)
m = powmod(c, d, n)
print(long_to_bytes(m))
#NSSCTF{p-1_smooth_with_factor}
posted @ 2025-03-11 14:35  sevensnight  阅读(36)  评论(0)    收藏  举报