Math Cocktail
from secret import key
x = key
M = 94665789456132156456789461321289656332321
n = 123456789123456789
k = x + pow(x,-1,M)
result = pow(x,n,M) + pow(x,-n,M)
print("k = " + str(k))
flag = "SICTF{"+str(result)+"}"
#k = 15396893775857205606087136852231851457937
首先讲一下非预期做法:构造多项式
k = x + pow(x,-1,M)可以写成下面这种形式
f(x)=x**2-k*x+1 mod M
因为里面只有一个x是未知数,所以就这样直接构造求解x
#sage
M = 94665789456132156456789461321289656332321
n = 123456789123456789
k = 15396893775857205606087136852231851457937
P.<x>=PolynomialRing(Zmod(M))
f=x**2-k*x+1
#root()函数用于求多项式f的根
#multiplicities=False为了防止重复根,即f=(x-1)**2
#会有重根1
x = int(f.roots(multiplicities=False)[0])
result = pow(x,n,M) + pow(x,-n,M)
print("SICTF{%s}"%(result))
或许建议这里这样写:x = int(f.monic().roots(multiplicities=False)[0])
monic()函数用于将x**2的系数进行首一化,例f=(x-1)*(x-2)
预期解:
转换成矩阵快速幂
求解
k = x + x^{-1} mod M
result = x^n + x^{-n} mod M
看起来比较整齐
先来看一下快速幂
的算法:
def modular_exponentiation(base, b, M):
result = 1
base = base % M
while b > 0:
if b & 1:
result = (result * base) % M
b >>= 1
base = (base * base) % M
return result
这里也只是将数变成矩阵进行运算
这里存在一种递推关系:
可以用以下矩阵表示:
完整的脚本如下:
def multiply_matrices(a, b):
res = [[0, 0], [0, 0]]
for i in range(0, 2):
for j in range(0, 2):
for p in range(0, 2):
res[i][j] = (res[i][j] + a[i][p] * b[p][j]) % M
return res
M = 94665789456132156456789461321289656332321
n = 123456789123456789
k = 15396893775857205606087136852231851457937
base = [[k, 1], [-1, 0]]
ans = [[(k*k-2) % M, k % M], [0, 0]]
b = n - 2
while b > 0:
if b & 1:
ans = multiply_matrices(ans, base)
base = multiply_matrices(base, base)
b >>= 1
print((ans[0][0] + M) % M)
Smooth
题目:
def getT1ngPrime(bits):
while True:
n = 2
while n.bit_length() < bits:
n *= choice(sieve_base)
if isPrime(n + 1):
return n + 1
e = 0x10001
p = getT1ngPrime(2048)
q = getT1ngPrime(2048)
n = p * q
c = pow(flag, e, n)
print("n =",n)
print("c =",c)
p-1光滑数
,这里sieve_base
的素数集最大应该小于等于104,729
按之前的脚本发现有点问题,因为我之前脚本设置的那个上界是e=65537,即公钥
先上脚本:
from Crypto.Util.number import *
import gmpy2
def Pollard(n):
a=2
while True:
for i in range(2,80000):
a=pow(a,i,n)
for j in range(80000,104729+1):
a=pow(a,j,n)
if j % 15 ==0:
d=GCD(a-1,n)
if(1<d<n):
return(d)
a+=1
n = 11353462911659482113796537452147300926058319193410149519981293344545095869273822230953023429933867057788424748612924709948861133348747189832397098293375764081790597820832766019459982124608221261607650511397189714784056313299551817534654742174637343804047231232241364089289257964139944018168155573510980260130960125621306919129390727418251555408239157881843225479158237727969284756513805560836003067115936987292751142016846824024901372913577548599978847860303760659677939193351221798796221804998385095596961591093782162020167439948314063423204757741472210008357888290333170757522814768955797167174930629344666183821709125207308525214263797625499327774875517941662523738827284067304929843343871569023248931759251331056863803201916908875256305736551124386988450879913404808869417817363510363373493093139804372817316366990863872781848240937733101758906281563575413208242901819275013539759479445299894840593737457394207415306989963459347994339058584475533786264375696277942369426844216474662828121334192775480587740071776080691560820922589751966526187341539255661442517814436944781114380877453502120302247547983180059537220197840688418898830571100216529994749464486853212098379822895838120836692532849021875818941979891105837972315129986493
c = 4598142980961588614870523368474306387497434303187254927457676265871592231881441246092917258758503624096206624791819316260705668875764048374035213672138915662719877795747211803584360349151646264274341548770123417923229997374982757324397146348908248704115062655445309042278469908831635522908894918382861563762003781223067210316435231509359575745828484177064520417698784251000631935361105284031848497200100561554984257265297077176545082009710252149167922123535451717313588884862304552508619154651546264753192894485610685402565486840707709012364088270364787452130288293053818329408433642977483320525542674345001200312959241276966417288770125166249156122793451000156544563900072606708005901579238109781720805374132101363788622676000360345128868422751829657184702090198806325558601552728909032627597688702884484377994243047876011323705947461799669488497113582621976154428096812072612119422667669321557427061098391558516935530727451865151957035156100271891977310043273298085691419672779758845492888551759393825925266903887942750052210444677062600227218953570162640164207895883301679126000642791876167281967081725589618329012476305157314322062703122134504285038691938912783524944917966615556902938825590064899700174139252191278691620663355243
e=65537
p=Pollard(n)
q=n//p
e=0x10001
d=int(gmpy2.invert(e,(p-1)*(q-1)))
m=pow(c,d,n)
print(long_to_bytes(m))
这里的第一部分先求2-8000的模运算(加快运算)也可以和下面写到一起
另外下面的if j % 15 ==0
每15次进行一次判断,也是为了加快速度
这里的判断也可以不写,都能求出结果
next_prime
from Crypto.Util.number import getPrime
from gmpy2 import next_prime
from select import flag
p = getPrime(1024)
q = getPrime(1024)
e = 65537
n = p * q
c = pow(flag, e, n)
gift = n * next_prime(p) * next_prime(q)
print("n =", n)
print("c =", c)
print("gift =", gift)
已知
p1=next_prime§
q1=next_prime(q)
所以,gift=p*q*p1*q1=p*p1*q*q1
我这里故意将写成pp1q*q1
已知p和p1较近,q和q1较近
所以这里可以采用fermat attack
攻击
from gmpy2 import isqrt
def fermat(n):
a = isqrt(n)
b2 = a*a - n
b = isqrt(n)
count = 0
while b*b != b2:
a = a + 1
b2 = a*a - n
b = isqrt(b2)
count += 1
pp1 = a+b
qq1 = a-b
assert n == pp1* qq1
return pp1, qq1
gitf = 143003048136494625720615623612005913472507924053937690079082986485649969355472743235179770036996193641198750946508667945561623931811236977039763581123681134310890547763107653222776992418543178066390387385209825190685606728024120446212807710589806258669458993047631033905702244902809204039169931629358263456702579067559691338668237882496453568585374905432631312417129535623987837367199215661733043851565981435234933986864857569158677737153423060041120732727135186371678287680926662892691327401787213342106281956461499522723795617869239148528294553548775690229067500104867437905746412645684721821428282431567702986879179533855920546700706123995719114359958306882907020982377260255340490340263938995699635287224549324332962230238510191824829224191551900441011605052418697617085549543103391184965537110312684637038510114533398510307173011690076219892318860903556489256383303693074652155424333388152193775840529985682153395008472897617946636734810609200156268438329402662168752285341847607694230848883249991722691539384542468611397615969487669898094687344847452861774236267516878551680397732564006255256825307533960791695267034807439791627895625581061889926276814228469856614838307012696777026973517086921078389474757196549594972814371353
print(fermat(gitf))
分解后的结果是p*p1
和q*q1
(mpz(11958388191411693159737723233868177200642855312771636589272066925180521736238782088222469544720240237292008558651656242716943228927612911153093905350043065811853776453271082678856297734699816670221066298151571078839575715976634390967727901295936522621706645886864683564184184197808626753747618171580292981776887266251016248499554323251705232058745804684256111703628972069650775058115602133769108831724103514611120659100631824316604826459671342341853346558301171183469890641811094484275459302059396543872703027605675370726907157057590786571486694601685261186359531868124819845268097400057088719792082052415620086105777), mpz(11958388191411693159737723233868177200642855312771636589272066925180521736238782088222469544720240237292008558651656242716943228927612911153093905350043065811853776453271082678856297734699816670221066298151571078839575715976634390967727901295936522621706645886864683564184184197808626753747618171580292981650975776687890350956135825641676449384715757742117309341641918612127453236552571397813972524980489740218302374188610847416719797756557901341389634787972523356448811982436717249582097249220526638640561439149514519252164274221154541174636417900091412142918587380553083915965133117304784080009374354680446804083689))
因为这里还给了n=p*q,n的具体值也知道,所以这里就比较好求解了
如果不知道n的值,其实也好解,就是把pp1开根号,找next_prime(isqrt(pp1)就是p1
下面就是正常RSA了
import gmpy2
from Crypto.Util.number import *
n = 11958388191411693159737723233868177200642855312771636589272066925180521736238782088222469544720240237292008558651656242716943228927612911153093905350043065811853776453271082678856297734699816670221066298151571078839575715976634390967727901295936522621706645886864683564184184197808626753747618171580292981571324190267014128877345111473870762554461674841623076501341477084318792110624423283610948627697772395662746329206056210266975821093875870239401934123066690637191790327090291595067248967533200784706397544202070440488806825607916659163953805033205530899551496221506129549542556866837853127119809134360611350153589
c = 10602368727908312334676265892975307612231309319511015017178654564186172749979627738052483995870388025140270600159107954524376993980949045647370337520644299969292550299798129717198074042121264370311983929042594290226321121639097714569204574387632530578153623781118813035223106106430716561113649761388347227207862016222328885951443891878767280730866193302995220736592745950808566359750940949520997722511969961743175777398751576595421456387998438214806188903746057855596476380404784738717555105866919649086601807350830108805521710188675565963765427930594177874353694184805979235854934856122125278853834603734029710968348
gift = 143003048136494625720615623612005913472507924053937690079082986485649969355472743235179770036996193641198750946508667945561623931811236977039763581123681134310890547763107653222776992418543178066390387385209825190685606728024120446212807710589806258669458993047631033905702244902809204039169931629358263456702579067559691338668237882496453568585374905432631312417129535623987837367199215661733043851565981435234933986864857569158677737153423060041120732727135186371678287680926662892691327401787213342106281956461499522723795617869239148528294553548775690229067500104867437905746412645684721821428282431567702986879179533855920546700706123995719114359958306882907020982377260255340490340263938995699635287224549324332962230238510191824829224191551900441011605052418697617085549543103391184965537110312684637038510114533398510307173011690076219892318860903556489256383303693074652155424333388152193775840529985682153395008472897617946636734810609200156268438329402662168752285341847607694230848883249991722691539384542468611397615969487669898094687344847452861774236267516878551680397732564006255256825307533960791695267034807439791627895625581061889926276814228469856614838307012696777026973517086921078389474757196549594972814371353
pp1=11958388191411693159737723233868177200642855312771636589272066925180521736238782088222469544720240237292008558651656242716943228927612911153093905350043065811853776453271082678856297734699816670221066298151571078839575715976634390967727901295936522621706645886864683564184184197808626753747618171580292981776887266251016248499554323251705232058745804684256111703628972069650775058115602133769108831724103514611120659100631824316604826459671342341853346558301171183469890641811094484275459302059396543872703027605675370726907157057590786571486694601685261186359531868124819845268097400057088719792082052415620086105777
qq1=11958388191411693159737723233868177200642855312771636589272066925180521736238782088222469544720240237292008558651656242716943228927612911153093905350043065811853776453271082678856297734699816670221066298151571078839575715976634390967727901295936522621706645886864683564184184197808626753747618171580292981650975776687890350956135825641676449384715757742117309341641918612127453236552571397813972524980489740218302374188610847416719797756557901341389634787972523356448811982436717249582097249220526638640561439149514519252164274221154541174636417900091412142918587380553083915965133117304784080009374354680446804083689
#p1q1=gitf//n
p1q1=11958388191411693159737723233868177200642855312771636589272066925180521736238782088222469544720240237292008558651656242716943228927612911153093905350043065811853776453271082678856297734699816670221066298151571078839575715976634390967727901295936522621706645886864683564184184197808626753747618171580292981856538852671892470578345037419510918888999887584750344543929413597459436184043750247972132729006820859166676704083186461466348803122353373443841047223207003902726912297157520138790307583746722397806866922553119449490264605670828668582169307468571142429726623027171774211690673650524019672681647272735455541405077
print(gmpy2.gcd(n,pp1))
p=gmpy2.gcd(n,pp1)
q=gmpy2.gcd(n,qq1)
e = 65537
d=gmpy2.invert(e,(p-1)*(q-1))
print(long_to_bytes(pow(c,d,n)))