from sage.all import * from Crypto.Util.number import * from gmpy2 import *
n = 6290400850108673527783456723558868077251853788073859360516042680251422818079380463161520548743184302018140978345372703177688378631564416901363981788817257 c = 3018879496435827891565409624549580574355607699876796814908055868300197064252462047054251836059387617618529706009316747223510404878163964048672091931778452 e = 65537 pbits = 256
phi = (p-1)*(q-1) d = invert(e,phi) flag = int(pow(c,d,n)) print(long_to_bytes(flag))
1.3、已知p的低位攻击
既然已知高位能恢复原先的p,那么如果我们知道p的低位呢
答案很明显也是可以的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
from Crypto.Util.number import * from secret import flag p = getPrime(1024) q = getPrime(1024) n = p*q m = bytes_to_long(flag) e = 65537 c = pow(m, e, n)
''' n = 21595945409392994055049935446570173194131443801801845658035469673666023560594683551197545038999238700810747167248724184844583697034436158042499504967916978621608536213230969406811902366916932032050583747070735750876593573387957847683066895725722366706359818941065483471589153682177234707645138490589285500875222568286916243861325846262164331536570517513524474322519145470883352586121892275861245291051589531534179640139953079522307426687782419075644619898733819937782418589025945603603989100805716550707637938272890461563518245458692411433603442554397633470070254229240718705126327921819662662201896576503865953330533 c = 1500765718465847687738186396037558689777598727005427859690647229619648539776087318379834790898189767401195002186003548094137654979353798325221367220839665289140547664641612525534203652911807047718681392766077895625388064095459224402032253429115181543725938853591119977152518616563668740574496233135226296439754690903570240135657268737729815911404733486976376064060345507410815912670147466261149162470191619474107592103882894806322239740349433710606063058160148571050855845964674224651003832579701204330216602742005466066589981707592861990283864753628591214636813639371477417319679603330973431803849304579330791040664 p = 1426723861968216959675536598409491243380171101180592446441649834738166786277745723654950385796320682900434611832789544257790278878742420696344225394624591657752431494779 '''
n = 21595945409392994055049935446570173194131443801801845658035469673666023560594683551197545038999238700810747167248724184844583697034436158042499504967916978621608536213230969406811902366916932032050583747070735750876593573387957847683066895725722366706359818941065483471589153682177234707645138490589285500875222568286916243861325846262164331536570517513524474322519145470883352586121892275861245291051589531534179640139953079522307426687782419075644619898733819937782418589025945603603989100805716550707637938272890461563518245458692411433603442554397633470070254229240718705126327921819662662201896576503865953330533
c = 1500765718465847687738186396037558689777598727005427859690647229619648539776087318379834790898189767401195002186003548094137654979353798325221367220839665289140547664641612525534203652911807047718681392766077895625388064095459224402032253429115181543725938853591119977152518616563668740574496233135226296439754690903570240135657268737729815911404733486976376064060345507410815912670147466261149162470191619474107592103882894806322239740349433710606063058160148571050855845964674224651003832579701204330216602742005466066589981707592861990283864753628591214636813639371477417319679603330973431803849304579330791040664
c = 49448440304854831648796534024125601382006282873198989997965557974794200333763817072355620545318651927253247674282578472637671741164408087215327482745901235293974786619481946963756529643023816474028709984009212852065178750039594108019217271743973042473197736068985706708503716012186147977316095727799381598075488417125
n = 28847074924932453349543409136399812128594610949367020026474778343570858319481313455200890189364023790182887175049408105958843453263073050626086662142940263874460213271683958427975341123423883215407111909499389249677340455477004237510991188529190235171007660645641687224704887400900068278836154730644879715422040757103147552875954913961588149167053461868101745063648215554184664115626793497487765708744642552805937987823454039925728887745567746569963466846339068171354494330823482202581747310450407677264654959638952096601645772638052521701110952634257302519671771900589919411338060623904602870338988690057676936333193
from Crypto.Util.number import * from secret import flag p = getPrime(512) q = getPrime(512) assert GCD(3, (p-1)*(q-1)) != 1 assertlen(flag) == 40 assert flag.startswith(b'DASCTF{') assert flag.endswith(b'}') n = p*q m = bytes_to_long(flag[7:-1]+b'12345678900987654321') e = 3 c = pow(m, e, n)
print("n =", n) print("m =", m&((1<<350)-1)) print("c =", c)
''' n = 78143938921360185614860462235112355256968995028076215097413461371745388165946555700961349927305255136527151965763804585057604387898421720879593387223895933656350645970498558271551701970896688207206809537892771605339961799334047604053282371439410751334173463317244016213693285842193635136764938802757014669091 m = 1906077032611187208365446696459387107800629785754941498024021333398862239730761050657886407994645536780849 c = 50130000135496687335562420162077023127865865388254124043997590968769445787929013990729805222613912997653046528125102370938788632651827553831996692788561639714991297669155839231144254658035090111092408296896778962224040765239997700906745359526477039359317216610131441370663885646599680838617778727787254679678 '''
这里一样就不多说了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
from gmpy2 import * from Crypto.Util.number import *
n = 78143938921360185614860462235112355256968995028076215097413461371745388165946555700961349927305255136527151965763804585057604387898421720879593387223895933656350645970498558271551701970896688207206809537892771605339961799334047604053282371439410751334173463317244016213693285842193635136764938802757014669091 m_low = 1906077032611187208365446696459387107800629785754941498024021333398862239730761050657886407994645536780849 c = 50130000135496687335562420162077023127865865388254124043997590968769445787929013990729805222613912997653046528125102370938788632651827553831996692788561639714991297669155839231144254658035090111092408296896778962224040765239997700906745359526477039359317216610131441370663885646599680838617778727787254679678
e = 3
PR.<x> = PolynomialRing(Zmod(n))
f = (x*2^350 + m_low)**e - c # 构造的模多项式 f = f.monic() root = f.small_roots(X=2^66,beta=0.5)[0] # 计算模多项式的小整数根 print('root =',root)
defgenarate_emojiiiiii_prime(nbits, base=0): whileTrue: p = getPrime(base // 32 * 32) if base >= 3else0 for i inrange(nbits // 8 // 4 - base // 32): p = (p << 32) + get_random_emojiiiiii() # 猜一猜 if isPrime(p): return p
m = bytes_to_long(flag.encode()+ "".join([long_to_bytes(get_random_emojiiiiii()).decode() for _ inrange(5)]).encode()) p = genarate_emojiiiiii_prime(512, 224) q = genarate_emojiiiiii_prime(512)
n = p * q e = "💯" c = pow(m, bytes_to_long(e.encode()), n)
p0 = '😘😾😂😋😶😾😳😷' n = 156583691355552921614631145152732482393176197132995684056861057354110068341462353935267384379058316405283253737394317838367413343764593681931500132616527754658531492837010737718142600521325345568856010357221012237243808583944390972551218281979735678709596942275013178851539514928075449007568871314257800372579 c = 47047259652272336203165844654641527951135794808396961300275905227499051240355966018762052339199047708940870407974724853429554168419302817757183570945811400049095628907115694231183403596602759249583523605700220530849961163557032168735648835975899744556626132330921576826526953069435718888223260480397802737401
p0_ = 108837065531980906150333850570890620719343963272506332719822248235755953428663 n = 156583691355552921614631145152732482393176197132995684056861057354110068341462353935267384379058316405283253737394317838367413343764593681931500132616527754658531492837010737718142600521325345568856010357221012237243808583944390972551218281979735678709596942275013178851539514928075449007568871314257800372579 c = 47047259652272336203165844654641527951135794808396961300275905227499051240355966018762052339199047708940870407974724853429554168419302817757183570945811400049095628907115694231183403596602759249583523605700220530849961163557032168735648835975899744556626132330921576826526953069435718888223260480397802737401
a=4036991100
from tqdm import tqdm for i in tqdm(range(100)): PR.<x> = PolynomialRing(Zmod(n)) f = x * 2^288 + p0_ + (a+i)*2^256 f = f.monic() roots = f.small_roots(X=2^225, beta=0.4,epsilon=0.04)
if roots: x = roots[0] p_candidate = int(x * 2^288 + p0_ + (a+i)*2^256) if n % p_candidate == 0: print("Found p:", p_candidate) q_candidate = n // p_candidate break
from gmpy2 import * from random import * from libnum import *
for i in m1: for j in m2: m=solve_crt([int(i[0]),int(j[0])],[int(p),int(q)]) print(long_to_bytes(int(m))) if b'TGCTF' in long_to_bytes(int(m)): print(long_to_bytes(int(m)).decode())
1.2p泄露位数不够且无法爆破
HGAME 2023
这里为什么说无法爆破呢,因为要爆破的数量级太大
1 2 3 4 5 6 7 8 9 10 11 12 13
defcreate_keypair(nbits): p = getPrime(nbits // 2) q = getPrime(nbits // 2) N = p*q phi = (p-1)*(q-1) e = 65537 d = inverse(e, phi) leak = p >> 253 return N, e, d, leak
n = 68340867186438223292118569682710524595966327481168801678255800028919163918249557519447553078528255888326840419621716908729880235244230459900539486879943421761586611726942757775742624070088176246368128990077459966006579285028594729801017390816903003704541109757846868073362640037019813128220657114558520107057
pbits = 512
for i in trange(2**5): p4 = 531320819410375258952658395582915285878636410772332266245849790153420724865787<<(253-248) p4 = p4 + i kbits = pbits - p4.nbits() p4 = p4 << kbits PR.<x> = PolynomialRing(Zmod(n)) f = x + p4 roots = f.small_roots(X=2^kbits, beta=0.4, epsilon=0.01) if roots: p = p4+int(roots[0]) if n%p==0: print(i,p) break q = n//p e = 65537 c = 0x29d543c73f4175f22440eef5954184e9d740cd3785011d560431861ccf6c4ff380d46ad948f9888e8cac2f5e38ce5e994f023d7195b78439b90d53ad23a730cc99b1b75dae1aba416cb6e645c5d135de906be54f344daba47a10492183d03211bfbaa45c09be2bb1913b1453e0538db95c56140cb78dd9c43d21f8312245ef7d f = (p-1)*(q-1) d = inverse_mod(e,f) m = pow(c,d,n) print(bytes.fromhex(hex(m)[2:]))
''' N = 135500646574582511239845764710311769260801998982429500680171919823431178899526463566215834234383331374445093363969218810906991784569340270510936759183504496584225937614940086329775325893307453919055830270986601152002191368431527285285313669979358099782497422114870417519470053198217401297960844455029559146309 e = 65537 c = 41763956818640145556632229720626372656921875856507389014855753965024986594502113237270745517422792354256348958542864591249410500750410658988509136242435502259172258432676502846729088278202750721760451160668653746019965695721844819587671602925551448624324524027931677927410810126647175483982178300855471710099 h = 918578024558168836638919636090777586135497638818209533615420650282292168631485 '''
这里就是原题搬家了,这里就不再多说了
1.3P泄露的位数够但需要调整参数
Mini L-CTF Ezfactor
1 2 3 4 5 6 7
p.bit_length() == q.bit_length() == 768
gift = p>>360
gift = 484571358830397929370234740984952703033447536470079158146615136255872598113610957918395761289775053764210538009624146851126
n = 1612520630363003059353142253089981533043311564255746310310940263864745479492015266264329953981958844235674179099410756219312942121244956701500870363219075525408783798007163550423573845701695879459236385567459569561236623909034945892869546441146006017614916909993115637827270568507869830024659905586004136946481048074461682125996261736024637375095977789425181258537482384460658359276300923155102288360474915802803118320144780824862629986882661190674127696656788827
n = 1612520630363003059353142253089981533043311564255746310310940263864745479492015266264329953981958844235674179099410756219312942121244956701500870363219075525408783798007163550423573845701695879459236385567459569561236623909034945892869546441146006017614916909993115637827270568507869830024659905586004136946481048074461682125996261736024637375095977789425181258537482384460658359276300923155102288360474915802803118320144780824862629986882661190674127696656788827
import gmpy2 from tqdm import * from Crypto.Util.number import *
n = 139167681803392690594490403105432649693546256181767408269202101512534988406137879788255103631885736461742577594980136624933914700779445704490217419248411578290305101891222576080645870988658334799437317221565839991979543660824098367011942169305111105129234902517835649895908656770416774539906212596072334423407 c1 = 11201139662236758800406931253538295757259990870588609533820056210585752522925690049252488581929717556881067021381940083808024384402885422258545946243513996 c2 = 112016152270171196606652761990170033221036025260883289104273504703557624964071464062375228351458191745141525003775876044271210498526920529385038130932141551598616579917681815276713386113932345056134302042399379895915706991873687943357627747262597883603999621939794450743982662393955266685255577026078256473601 e = 65537 pbits = 512
p_high = c1 >> 256 for i in trange(2**8): p4 = p_high << 8 #这里需要先爆破8位,使得知道264位以后再恢复p p4 = p4 + i kbits = pbits - p4.nbits() p4 = p4 << kbits R.<x> = PolynomialRing(Zmod(n)) f = x + p4 res = f.small_roots(X=2^kbits, beta=0.4, epsilon=0.01) if res != []: p = p4 + int(x[0]) q = n // p d = gmpy2.invert(e,(p-1)*(q-1)) m = pow(c2,d,n) print(long_to_bytes(int(m))) break
c = 120440199294949712392334113337541924034371176306546446428347114627162894108760435789068328282135879182130546564535108930827440004987170619301799710272329673259390065147556073101312748104743572369383346039000998822862286001416166288971531241789864076857299162050026949096919395896174243383291126202796610039053
n = 143413213355903851638663645270518081058249439863120739973910994223793329606595495141951165221740599158773181585002460087410975579141155680671886930801733174300593785562287068287654547100320094291092508723488470015821072834947151827362715749438612812148855627557719115676595686347541785037035334177162406305243
PR.<x> = PolynomialRing(Zmod(n))
for length in trange(20,50):
suffix = bytes_to_long(hash(str(length)))
f = (256^32*x + suffix)^3 - c
f = f.monic()
res = f.small_roots(X=256^length,beta=1,epsilon=0.05)
c = 120440199294949712392334113337541924034371176306546446428347114627162894108760435789068328282135879182130546564535108930827440004987170619301799710272329673259390065147556073101312748104743572369383346039000998822862286001416166288971531241789864076857299162050026949096919395896174243383291126202796610039053
n = 143413213355903851638663645270518081058249439863120739973910994223793329606595495141951165221740599158773181585002460087410975579141155680671886930801733174300593785562287068287654547100320094291092508723488470015821072834947151827362715749438612812148855627557719115676595686347541785037035334177162406305243
import gmpy2 import itertools def small_roots(f, bounds, m=1, d=None): if not d: d = f.degree()
R = f.base_ring() N = R.cardinality()
f /= f.coefficients().pop(0) f = f.change_ring(ZZ)
G = Sequence([], f.parent()) for i in range(m + 1): base = N ^ (m - i) * f ^ i for shifts in itertools.product(range(d), repeat=f.nvariables()): g = base * prod(map(power, f.variables(), shifts)) G.append(g)
factors = [monomial(*bounds) for monomial in monomials] for i, factor in enumerate(factors): B.rescale_col(i, factor)
B = B.dense_matrix().LLL()
B = B.change_ring(QQ) for i, factor in enumerate(factors): B.rescale_col(i, 1 / factor)
H = Sequence([], f.parent().change_ring(QQ)) for h in filter(None, B * monomials): H.append(h) I = H.ideal() if I.dimension() == -1: H.pop() elif I.dimension() == 0: roots = [] for root in I.variety(ring=ZZ): root = tuple(R(root[var]) for var in f.variables()) roots.append(root) return roots
p = 8813834626918693034209829623386418111935369643440896703895290043343199520112218432639643684400534953548489779045914955504743423765099014797611981422650409
a = 2817275225516767613658440250260394873529274896419346861054126128919212362519165468003171950475070788320195398302803745633617864408366174315471102773073469
b = 1763620527779958060718182646420541623477856799630691559360944374374235694750950917040727594731391703184965719358552775151767735359739899063298735788999711
c = 2298790980294663527827702586525963981886518365072523836572440106026473419042192180086308154346777239817235315513418426401278994450805667292449334757693881
for shifts in itertools.product(range(d), repeat=f.nvariables()):
g = base * prod(map(power, f.variables(), shifts))
G.append(g)
B, monomials = G.coefficient_matrix()
monomials = vector(monomials)
factors = [monomial(*bounds) for monomial in monomials]
for i, factor in enumerate(factors):
B.rescale_col(i, factor)
B = B.dense_matrix().LLL()
B = B.change_ring(QQ)
for i, factor in enumerate(factors):
B.rescale_col(i, 1 / factor)
H = Sequence([], f.parent().change_ring(QQ))
for h in filter(None, B * monomials):
H.append(h)
I = H.ideal()
if I.dimension() == -1:
H.pop()
elif I.dimension() == 0:
roots = []
for root in I.variety(ring=ZZ):
root = tuple(R(root[var]) for var in f.variables())
roots.append(root)
return roots
return []
p = 8813834626918693034209829623386418111935369643440896703895290043343199520112218432639643684400534953548489779045914955504743423765099014797611981422650409
a = 2817275225516767613658440250260394873529274896419346861054126128919212362519165468003171950475070788320195398302803745633617864408366174315471102773073469
b = 1763620527779958060718182646420541623477856799630691559360944374374235694750950917040727594731391703184965719358552775151767735359739899063298735788999711
c = 2298790980294663527827702586525963981886518365072523836572440106026473419042192180086308154346777239817235315513418426401278994450805667292449334757693881
from Crypto.Util.number import * from secret import flag
m = bytes_to_long(flag) p = getPrime(512) q = getPrime(512) n = p * q e = getPrime(64) dp = inverse(e, p - 1) print(f"n = {n}") print(f"e = {e}") print(f"dph = {dp >> 115 <<115}") print(f"c = {pow(m,e,n)}")
""" n = 99808598778276923350368946118829564161543192771741967304113142692217693457972421525964898372688505220132024575461230316318177765543298394717753949509523080306599063058808987337840085569950414884529534449801215600413303898393849792345972321407524999652571659221193654323489992751031985715286873931985408130197 e = 9550490518460184889 dph = 4239371595915398923623854132330356869028911602649930928560125044718768467773415379438150660838271530302945945606708178367182566660953659123879375907323904 c = 18661814437233106799783882536249538287931377372915334052147813302071480339780465378376553936510407532657463793836895065758256947765504246845601788497861702555369338586376572381147331367628136147491699775987490116748428373153021965663362046971594255692960097313870139384700219810117047587229718472407783734575 """
from Crypto.Util.number import * import gmpy2 import itertools
def small_roots(f, bounds, m=1, d=None): if not d: d = f.degree() print(d) R = f.base_ring() N = R.cardinality() f /= f.coefficients().pop(0) f = f.change_ring(ZZ) G = Sequence([], f.parent()) for i in range(m + 1): base = N ^ (m - i) * f ^ i for shifts in itertools.product(range(d), repeat=f.nvariables()): g = base * prod(map(power, f.variables(), shifts)) G.append(g) B, monomials = G.coefficient_matrix() monomials = vector(monomials) factors = [monomial(*bounds) for monomial in monomials] for i, factor in enumerate(factors): B.rescale_col(i, factor) B = B.dense_matrix().LLL() B = B.change_ring(QQ) for i, factor in enumerate(factors): B.rescale_col(i, 1 / factor) H = Sequence([], f.parent().change_ring(QQ)) for h in filter(None, B * monomials): H.append(h) I = H.ideal() if I.dimension() == -1: H.pop() elif I.dimension() == 0: roots = [] for root in I.variety(ring=ZZ): root = tuple(R(root[var]) for var in f.variables()) roots.append(root) return roots return []
n = 99808598778276923350368946118829564161543192771741967304113142692217693457972421525964898372688505220132024575461230316318177765543298394717753949509523080306599063058808987337840085569950414884529534449801215600413303898393849792345972321407524999652571659221193654323489992751031985715286873931985408130197 e = 9550490518460184889 c = 18661814437233106799783882536249538287931377372915334052147813302071480339780465378376553936510407532657463793836895065758256947765504246845601788497861702555369338586376572381147331367628136147491699775987490116748428373153021965663362046971594255692960097313870139384700219810117047587229718472407783734575 leak = 4239371595915398923623854132330356869028911602649930928560125044718768467773415379438150660838271530302945945606708178367182566660953659123879375907323904
R.<x,y> = PolynomialRing(Zmod(n)) f = e * (leak + x) + (y - 1) res = small_roots(f,(2^115,2^64),m=2,d=5) print(res) for root in res: dp_low = root[0] dp = leak + dp_low tmp = pow(2,e*dp,n) - 2 p = gmpy2.gcd(tmp,n) q = n // p d = inverse(e,(p-1)*(q-1)) m = pow(c,d,n) print(long_to_bytes(m))
n = 24240993137357567658677097076762157882987659874601064738608971893024559525024581362454897599976003248892339463673241756118600994494150721789525924054960470762499808771760690211841936903839232109208099640507210141111314563007924046946402216384360405445595854947145800754365717704762310092558089455516189533635318084532202438477871458797287721022389909953190113597425964395222426700352859740293834121123138183367554858896124509695602915312917886769066254219381427385100688110915129283949340133524365403188753735534290512113201932620106585043122707355381551006014647469884010069878477179147719913280272028376706421104753
C = [5300743174999795329371527870190100703154639960450575575101738225528814331152637733729613419201898994386548816504858409726318742419169717222702404409496156167283354163362729304279553214510160589336672463972767842604886866159600567533436626931810981418193227593758688610512556391129176234307448758534506432755113432411099690991453452199653214054901093242337700880661006486138424743085527911347931571730473582051987520447237586885119205422668971876488684708196255266536680083835972668749902212285032756286424244284136941767752754078598830317271949981378674176685159516777247305970365843616105513456452993199192823148760, 21112179095014976702043514329117175747825140730885731533311755299178008997398851800028751416090265195760178867626233456642594578588007570838933135396672730765007160135908314028300141127837769297682479678972455077606519053977383739500664851033908924293990399261838079993207621314584108891814038236135637105408310569002463379136544773406496600396931819980400197333039720344346032547489037834427091233045574086625061748398991041014394602237400713218611015436866842699640680804906008370869021545517947588322083793581852529192500912579560094015867120212711242523672548392160514345774299568940390940653232489808850407256752]
for shifts in itertools.product(range(d), repeat=f.nvariables()):
g = base * prod(map(power, f.variables(), shifts))
G.append(g)
B, monomials = G.coefficient_matrix()
monomials = vector(monomials)
factors = [monomial(*bounds) for monomial in monomials]
for i, factor in enumerate(factors):
B.rescale_col(i, factor)
B = B.dense_matrix().LLL()
B = B.change_ring(QQ)
for i, factor in enumerate(factors):
B.rescale_col(i, 1 / factor)
H = Sequence([], f.parent().change_ring(QQ))
for h in filter(None, B * monomials):
H.append(h)
I = H.ideal()
if I.dimension() == -1:
H.pop()
elif I.dimension() == 0:
roots = []
for root in I.variety(ring=ZZ):
root = tuple(R(root[var]) for var in f.variables())
roots.append(root)
return roots
return []
n = 24240993137357567658677097076762157882987659874601064738608971893024559525024581362454897599976003248892339463673241756118600994494150721789525924054960470762499808771760690211841936903839232109208099640507210141111314563007924046946402216384360405445595854947145800754365717704762310092558089455516189533635318084532202438477871458797287721022389909953190113597425964395222426700352859740293834121123138183367554858896124509695602915312917886769066254219381427385100688110915129283949340133524365403188753735534290512113201932620106585043122707355381551006014647469884010069878477179147719913280272028376706421104753
C = [5300743174999795329371527870190100703154639960450575575101738225528814331152637733729613419201898994386548816504858409726318742419169717222702404409496156167283354163362729304279553214510160589336672463972767842604886866159600567533436626931810981418193227593758688610512556391129176234307448758534506432755113432411099690991453452199653214054901093242337700880661006486138424743085527911347931571730473582051987520447237586885119205422668971876488684708196255266536680083835972668749902212285032756286424244284136941767752754078598830317271949981378674176685159516777247305970365843616105513456452993199192823148760, 21112179095014976702043514329117175747825140730885731533311755299178008997398851800028751416090265195760178867626233456642594578588007570838933135396672730765007160135908314028300141127837769297682479678972455077606519053977383739500664851033908924293990399261838079993207621314584108891814038236135637105408310569002463379136544773406496600396931819980400197333039720344346032547489037834427091233045574086625061748398991041014394602237400713218611015436866842699640680804906008370869021545517947588322083793581852529192500912579560094015867120212711242523672548392160514345774299568940390940653232489808850407256752]
c = 6187845844052645335477666563187579997555293403110620879123121166924703361821847984760733842049752886698011561451715570810292323756091403783920480396052120046379755571530451812078574368413924390017994278703794257118954968480994077586245800902748815905644287545189605031883291488844527496906890127546594960138582150272568163575590734246290813150131949296550974206595456421136190026954855755623761557179760444906148376433584795779131477110538212742401420633087881506416368853221110426491868881029814841479615979710066371796507692025126150957315754738584387325388998533227577023142894876376702128870643448600352603905149
n = 14195810221536708489210274086946022255792382922322850338983263099316341767896809249586174293795778082892237356582757544364274847341220303582304283372889068290282580493623042441421715338444710303281638639785784613434328659529884972238348336971186339482788748316527376410510261228354155806341136524162787121212184386900663470590652770503564816948407257603737938414126069053610568675347826390537145556511048774030823322301932088595499671755944744816524811272617200683384649389274196659297432212847319503330409792704612575414010711158873031786577877685578976140462539734553598745329712188216200905451774357282278403189943
c = 50810871938251627005285090837280618434273429940089654925377752488011128518767341675465435906094867261596016363149398900195250354993172711611856393548098646094748785774924511077105061611095328649875874203921275281780733446616807977350320544877201182003521199057295967111877565671671198186635360508565083698058
gift = 2391232579794490071131297275577300947901582900418236846514147804369797358429972790212
首先题目给出的是gift的高位
1
gift = pow((giftp + giftq + a*b), 2, phi)
看到gift的线性关系,可以先展开 gift = (p + a + q + b + a * b)2 mod phi
这里phi = n − (p + q) + 1
c = 50810871938251627005285090837280618434273429940089654925377752488011128518767341675465435906094867261596016363149398900195250354993172711611856393548098646094748785774924511077105061611095328649875874203921275281780733446616807977350320544877201182003521199057295967111877565671671198186635360508565083698058