defmul_THcurve(n, P): R = (0, 0) while n > 0: if n % 2 == 1: R = add_THcurve(R, P) P = add_THcurve(P, P) n = n // 2 return R
p = 10297529403524403127640670200603184608844065065952536889 a = 2 G = (8879931045098533901543131944615620692971716807984752065, 4106024239449946134453673742202491320614591684229547464)
FLAG = flag.lstrip(b'DASCTF{').rstrip(b'}') assertlen(FLAG) == 15 m = bytes_to_long(FLAG) assert m < p Q = mul_THcurve(m, G) print("Q =", Q) # Q = (6784278627340957151283066249316785477882888190582875173, 6078603759966354224428976716568980670702790051879661797)
p = 10297529403524403127640670200603184608844065065952536889 a = 2 G = (8879931045098533901543131944615620692971716807984752065, 4106024239449946134453673742202491320614591684229547464) Q = (6784278627340957151283066249316785477882888190582875173, 6078603759966354224428976716568980670702790051879661797)
# Q = G * m xg, yg = G xq, yq = Q d = (2*xg^3 + yg^3 + 1) * pow(xg*yg,-1,p) % p # dd = (2*xq^3 + yq^3 + 1) * pow(xq*yq,-1,p) % p == d A = [0,1,-1] R.<x,y,z> = Zmod(p)[] cubic = 2*x^3+y^3+z^3 - d*x*y*z E = EllipticCurve_from_cubic(cubic, A,morphism=True) # 由多项式方程生成一个曲线 Ee = EllipticCurve_from_cubic(cubic, A,morphism=False)
# E包含映射关系 G = E(G) Q = E(Q) order = Ee.order() print(order) m = G.discrete_log(Q) print(m) flag = b"DASCTF{" + long_to_bytes(m) + b"}" print(flag) # DASCTF{e@sy_cuRvL_c0o!}
# -------------------------------------find b c------------------------------------------
for i in tqdm(range(-100, 100)): P2 = mul_curve(i, G1, K1) if P2 == P1: c = i break
for i in tqdm(range(-100, 100)): Q2 = mul_curve(i, G1, K1) if Q2 == Q1: b = i break
print(f"b = {b}, c = {c}") # b = 98, c = 35 # --------------------------------------ECDLP--------------------------------------------
p = 770311352827455849356512448287 E = EllipticCurve(GF(p), [-c, b]) G = (584273268656071313022845392380 , 105970580903682721429154563816) P = (401055814681171318348566474726 , 293186309252428491012795616690) G = E(G) P = E(P) k = G.discrete_log(P)
from Crypto.Util.number import * from tqdm import tqdm import string
c = 356435791209686635044593929546092486613929446770721636839137 p = 898278915648707936019913202333 q = 814090608763917394723955024893 newm = b'X\xee\x1ey\x88\x01dX\xf6i\x91\x80h\xf4\x1f!\xa7"\x0c\x9a\x06\xc8\x06\x81\x15' m = bytes_to_long(newm) n = p * q
# --------------------brute_crack-------------------------------------- for i in tqdm(range(20, 60)): flag0 = b"DASCTF{" + b"\x00" * i + b"}" flag1 = b"DASCTF{" + b"\xff" * i + b"}" m0 = bytes_to_long(flag0) m1 = bytes_to_long(flag1) k0 = (m0 - m) // n k1 = (m1 - m) // n k = k0 while k <= k1: pm = k * n + m pmes = long_to_bytes(pm) if (pmes.startswith(b"DASCTF{") and pmes.endswith(b"}") andall(32 <= byte <= 126for byte in pmes)): print(f"Found potential flag (i={i}, k={k}): {pmes}") break if pm % 256 == ord('}'): k += 256 else: k += 1
# Found potential flag (i=28, k=181321970727117606593880360): b'DASCTF{o0p5_m3ssaGe_to0_b1g_nv93nd0}'
from Crypto.Util.number import * from tqdm import tqdm import string
c = 356435791209686635044593929546092486613929446770721636839137 p = 898278915648707936019913202333 q = 814090608763917394723955024893 n = p * q newm = b'X\xee\x1ey\x88\x01dX\xf6i\x91\x80h\xf4\x1f!\xa7"\x0c\x9a\x06\xc8\x06\x81\x15' c = bytes_to_long(newm)
prefix = b"DASCTF{" suffix = b"}" t = n centerMark = 79
# 遍历flag的长度 for i in tqdm(range(20, 40)): length = i k = length - len(prefix) - len(suffix) pc = c # 剥离前后缀的影响 pc = (pc - bytes_to_long(prefix) * pow(256, k + len(suffix), n) - bytes_to_long(suffix)) % n
# 获得明文的对应长整数 cc = pc * inverse_mod(256, n) % n sumConstant = sum(256^j for j inrange(k)) C = (cc - centerMark * sumConstant) % n
# 造格子 规约 M = matrix(ZZ, k + 2, k + 2) for index inrange(k): M[index, index] = 1 M[index, k+1] = t * 256^index M[k, k] = 1 M[k, k + 1] = -t * C M[k + 1, k + 1] = t * n L = M.BKZ() # print(L)
# 筛选可能的答案 for row in L: tag = 1 for num in row[:-2]: if num < 33 - centerMark or num > 126 - centerMark: tag = 0 break if tag: flag = "" for num in row[:-2][::-1]: flag += chr(num + centerMark) ifchr(centerMark) * 4notin flag: pflag = b"DASCTF{" + flag.encode() + b"}" print(f"length {i} , flag {pflag}") ''' 100%|██████████| 20/20 [00:00<00:00, 323.41it/s] length 36 , flag b'DASCTF{o0p5_m3ssaGe_to0_b1g_nv93nd0}' length 37 , flag b'DASCTF{+[ML"sIDDTCQ[,)Av6|LU.?-+rcB|}' length 38 , flag b'DASCTF{O=V-MT"B=oe2&T@3i}oXKE2:"DfV>n}' length 39 , flag b'DASCTF{@NmMm^1Pk@J3QXIA5D<OPXFF(HA{cVQ}' length 39 , flag b'DASCTF{cU5AW:?Gg!cR8Y*CK@kQAaMxAIH]l<Q}' length 39 , flag b'DASCTF{n^[ERBLa$Xe}^YhWP7nTLa0*@^%fToN}' length 39 , flag b'DASCTF{CBEL|Qs>g@qC9IMcWenU$j\\TZ)2$%T5}' length 39 , flag b"DASCTF{eA671MFQzT'C7:[7vX]J^G]OH^C>-ms}" '''
from Crypto.Util.number import * from gmpy2 import * from secret import flag
defdecode_e(e): if e > 1: mul = 1 for i inrange(1, e): mul *= i if e - mul % e - 1 == 0: mulmod = mul % e - e else: mulmod = mul % e return mulmod + decode_e(e - 1) else: return0
q = getPrime(1024) p = next_prime(q) n = p * q phi = (p - 1) * (q - 1) e = abs(decode_e(703440151)) c = pow(bytes_to_long(flag), e, n) print('n = {}\n' 'c = {}'.format(n, c))
''' n = 18770575776346636857117989716700159556553308603827318013591587255198383129370907809760732011993542700529211200756354110539398800399971400004000898098091275284235225898698802555566416862975758535452624647017057286675078425814784682675012671384340267087604803050995107534481069279281213277371234272710195280647747033302773076094600917583038429969629948198841325080329081838681126456119415461246986745162687569680825296434756908111148165787768172000131704615314046005916223370429567142992192702888820837032850104701948658736010527261246199512595520995042205818856177310544178940343722756848658912946025299687434514029951 c = 2587907790257921446754254335909686808394701314827194535473852919883847207482301560195700622542784316421967768148156146355099210400053281966782598551680260513547233270646414440776109941248869185612357797869860293880114609649325409637239631730174236109860697072051436591823617268725493768867776466173052640366393488873505207198770497373345116165334779381031712832136682178364090547875479645094274237460342318587832274304777193468833278816459344132231018703578274192000016560653148923056635076144189403004763127515475672112627790796376564776321840115465990308933303392198690356639928538984862967102082126458529748355566 '''
RSA问题 由函数decode_e给出,然后就是解一个相邻素数的RSA
先分析decode_e函数
首先计算e-1的阶乘mul
随后的判断式子e - mul % e - 1 == 0 用到了Wilson’s
Theorem 本质是判断是否为素数
即式子 当且仅当是素数时成立
如果是素数,那么就有 由Wilson’s Theorem 这里的是
如果是合数,假设存在分解 那么在计算阶乘的时候,必有 也就必定有 此时的就是0
但是存在几个例外 如果为
那么
综上对于式子decode_e(p)我们只需要计算小于等于的素数个数 对于所有的素数 自减1,对于除开之外的合数 不变
尝试写个脚本跑一下?但是时间复杂度太高
有什么办法简化吗,考虑对这种大范围使用素数筛法即Sieve of
Eratosthenes
from Crypto.Util.number import * from tqdm import tqdm import numpy as np n = 18770575776346636857117989716700159556553308603827318013591587255198383129370907809760732011993542700529211200756354110539398800399971400004000898098091275284235225898698802555566416862975758535452624647017057286675078425814784682675012671384340267087604803050995107534481069279281213277371234272710195280647747033302773076094600917583038429969629948198841325080329081838681126456119415461246986745162687569680825296434756908111148165787768172000131704615314046005916223370429567142992192702888820837032850104701948658736010527261246199512595520995042205818856177310544178940343722756848658912946025299687434514029951 c = 2587907790257921446754254335909686808394701314827194535473852919883847207482301560195700622542784316421967768148156146355099210400053281966782598551680260513547233270646414440776109941248869185612357797869860293880114609649325409637239631730174236109860697072051436591823617268725493768867776466173052640366393488873505207198770497373345116165334779381031712832136682178364090547875479645094274237460342318587832274304777193468833278816459344132231018703578274192000016560653148923056635076144189403004763127515475672112627790796376564776321840115465990308933303392198690356639928538984862967102082126458529748355566 goal = 703440151
res = 0 defcount_primes_with_sieve(p): if p < 2: return0 is_prime = np.ones(p + 1, dtype=bool) is_prime[0] = is_prime[1] = False for i inrange(2, int(p**0.5) + 1): if is_prime[i]: is_prime[i*i::i] = False return np.sum(is_prime) num = count_primes_with_sieve(goal) e = abs(num * -1 + 2) pp = floor(sqrt(n)) for i inrange(-10000, 10000): p = pp + i if n % p == 0: q = n // p phi = (p-1) * (q-1) assert gcd(e,phi) == 1 d = inverse_mod(e, phi) print(long_to_bytes(pow(c,d,n)))