题目:
from Crypto.Util.number import *
from random import choiceflag = b'NSSCTF{******}'def getMyPrime(nbits):while True:p = 1while p.bit_length() <= nbits:p *= choice(sieve_base)if isPrime(p-1):return p-1p = 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 = 63398538193562720708999492397588489035970399414238113344990243900620729661046648078623873637152448697806039260616826648343172207246183989202073562200879290937
e = 65537
c = 26971181342240802276810747395669930355754928952080329914687241779532014305320191048439959934699795162709365987652696472998140484810728817991804469778237933925
'''
解题思路:
- 当p是N的因数,并且p+1是光滑数,可以考虑使用Williams的p+1算法来分解N
知识拓展:
Williams的p+1算法
看不懂,懒得写
大整数分解算法 之 Williams’s p+1 算法原理 - TLSN - 博客园
解答:
from Crypto.Util.number import *
from gmpy2 import *
from itertools import countn = 63398538193562720708999492397588489035970399414238113344990243900620729661046648078623873637152448697806039260616826648343172207246183989202073562200879290937
e = 65537
c = 26971181342240802276810747395669930355754928952080329914687241779532014305320191048439959934699795162709365987652696472998140484810728817991804469778237933925def mlucas(v, a, n):v1, v2 = v, (v ** 2 - 2) % nfor bit in bin(a)[3:]: v1, v2 = ((v1 ** 2 - 2) % n, (v1 * v2 - v) % n) if bit == "0" else ((v1 * v2 - v) % n, (v2 ** 2 - 2) % n)return v1def primegen():yield 2yield 3yield 5yield 7yield 11yield 13ps = primegen() # yay recursionp = ps.__next__() and ps.__next__()q, sieve, n = p ** 2, {}, 13while True:if n not in sieve:if n < q:yield nelse:next, step = q + 2 * p, 2 * pwhile next in sieve:next += stepsieve[next] = stepp = ps.__next__()q = p ** 2else:step = sieve.pop(n)next = n + stepwhile next in sieve:next += stepsieve[next] = stepn += 2def ilog(x, b): # greatest integer l such that b**l <= x.l = 0while x >= b:x /= bl += 1return ldef attack(n):for v in count(1):for p in primegen():e = ilog(isqrt(n), p)if e == 0:breakfor _ in range(e):v = mlucas(v, p, n)g = gcd(v - 2, n)if 1 < g < n:return int(g), int(n // g) # g|nif g == n:breakp, q = attack(n)phi = (p-1)*(q-1)
d = invert(e, phi)
m = powmod(c, d, n)
print(long_to_bytes(m))
#NSSCTF{p+1_smooth_number}