[CISCN 2021初赛]rsa
1.题目
from flag import text,flag
import md5
from Crypto.Util.number import long_to_bytes,bytes_to_long,getPrimeassert md5.new(text).hexdigest() == flag[6:-1]msg1 = text[:xx]
msg2 = text[xx:yy]
msg3 = text[yy:]msg1 = bytes_to_long(msg1)
msg2 = bytes_to_long(msg2)
msg3 = bytes_to_long(msg3)p1 = getPrime(512)
q1 = getPrime(512)
N1 = p1*q1
e1 = 3
print pow(msg1,e1,N1)
print (e1,N1)p2 = getPrime(512)
q2 = getPrime(512)
N2 = p2*q2
e2 = 17
e3 = 65537
print pow(msg2,e2,N2)
print pow(msg2,e3,N2)
print (e2,N2)
print (e3,N2)p3 = getPrime(512)
q3 = getPrime(512)
N3 = p3*q3
print pow(msg3,e3,N3)
print (e3,N3)
print p3>>20019105765285510667553313898813498220212421177527647187802549913914263968945493144633390670605116251064550364704789358830072133349108808799075021540479815182657667763617178044110939458834654922540704196330451979349353031578518479199454480458137984734402248011464467312753683234543319955893
(3, 123814470394550598363280518848914546938137731026777975885846733672494493975703069760053867471836249473290828799962586855892685902902050630018312939010564945676699712246249820341712155938398068732866646422826619477180434858148938235662092482058999079105450136181685141895955574548671667320167741641072330259009L)
54995751387258798791895413216172284653407054079765769704170763023830130981480272943338445245689293729308200574217959018462512790523622252479258419498858307898118907076773470253533344877959508766285730509067829684427375759345623701605997067135659404296663877453758701010726561824951602615501078818914410959610
91290935267458356541959327381220067466104890455391103989639822855753797805354139741959957951983943146108552762756444475545250343766798220348240377590112854890482375744876016191773471853704014735936608436210153669829454288199838827646402742554134017280213707222338496271289894681312606239512924842845268366950
(17, 111381961169589927896512557754289420474877632607334685306667977794938824018345795836303161492076539375959731633270626091498843936401996648820451019811592594528673182109109991384472979198906744569181673282663323892346854520052840694924830064546269187849702880332522636682366270177489467478933966884097824069977L)
(65537, 111381961169589927896512557754289420474877632607334685306667977794938824018345795836303161492076539375959731633270626091498843936401996648820451019811592594528673182109109991384472979198906744569181673282663323892346854520052840694924830064546269187849702880332522636682366270177489467478933966884097824069977L)
59213696442373765895948702611659756779813897653022080905635545636905434038306468935283962686059037461940227618715695875589055593696352594630107082714757036815875497138523738695066811985036315624927897081153190329636864005133757096991035607918106529151451834369442313673849563635248465014289409374291381429646
(65537, 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147L)
7117286695925472918001071846973900342640107770214858928188419765628151478620236042882657992902
2.思路
我们观察代码:
msg1 = text[:xx]
msg2 = text[xx:yy]
msg3 = text[yy:]
将text分割成三段msg1,msg2,msg3
后面的部分都是给他们分别RSA加密,那么我们就开始一个一个求解
第一个e1等于3,很可能是低指数加密攻击,(我之前的文章也讲过低指数加密攻击(低指数广播攻击)_低指数攻击脚本-CSDN博客)
直接套用脚本
import gmpy2
import libnumdef decrypt_low_exponent(c, e, n, max_k=1000):for k in range(max_k + 1):possible_m_cubed = c + n * km, is_exact_root = gmpy2.iroot(possible_m_cubed, e)if is_exact_root:return mraise ValueError("解密失败,可能 m^e >= n 或 e 不适用")# 题目给定的参数
n = 123814470394550598363280518848914546938137731026777975885846733672494493975703069760053867471836249473290828799962586855892685902902050630018312939010564945676699712246249820341712155938398068732866646422826619477180434858148938235662092482058999079105450136181685141895955574548671667320167741641072330259009
e = 3
c = 19105765285510667553313898813498220212421177527647187802549913914263968945493144633390670605116251064550364704789358830072133349108808799075021540479815182657667763617178044110939458834654922540704196330451979349353031578518479199454480458137984734402248011464467312753683234543319955893# 解密
try:m = decrypt_low_exponent(c, e, n)print("解密后的整数 m =", m)print("解密后的字符串 =", libnum.n2s(int(m)).decode())
except ValueError as e:print("解密失败:", e)
运行结果:m=267334379257781603687613466720913534310764480084016847281446486946801530200295563483353634338157
第二部分,我们再看e2和e3,都是同一m,不同e,那么我们立刻联想到共模攻击共模攻击脚本_共模攻击 代码-CSDN博客
直接套用脚本
c1=54995751387258798791895413216172284653407054079765769704170763023830130981480272943338445245689293729308200574217959018462512790523622252479258419498858307898118907076773470253533344877959508766285730509067829684427375759345623701605997067135659404296663877453758701010726561824951602615501078818914410959610
c2=91290935267458356541959327381220067466104890455391103989639822855753797805354139741959957951983943146108552762756444475545250343766798220348240377590112854890482375744876016191773471853704014735936608436210153669829454288199838827646402742554134017280213707222338496271289894681312606239512924842845268366950
n1=111381961169589927896512557754289420474877632607334685306667977794938824018345795836303161492076539375959731633270626091498843936401996648820451019811592594528673182109109991384472979198906744569181673282663323892346854520052840694924830064546269187849702880332522636682366270177489467478933966884097824069977
n2=111381961169589927896512557754289420474877632607334685306667977794938824018345795836303161492076539375959731633270626091498843936401996648820451019811592594528673182109109991384472979198906744569181673282663323892346854520052840694924830064546269187849702880332522636682366270177489467478933966884097824069977
e1=17
e2=65537
import libnum
import gmpy2
s,s1,s2=gmpy2.gcdext(e1,e2)
print(s,s1,s2)
m=(pow(c1,s1,n1)*pow(c2,s2,n2)%n1)
print(m)
结果如下:
m=4193305853284549103821195807609492624095031428085219879448342104337322945001387680236011960472296815293233144303730273979905837762067652913308898433728800864776794638198055607422503065410595894676740531680367227696622352026247676452540064020322619036125381146346603655445487695574824919137
最后我们再看print p3>>200,泄露 p3 的高 312 位,属于p的高位泄露攻击
参照大佬的脚本,使用Coppersmith 方法 恢复了完整的 p
#p4已知高位
p3 = 7117286695925472918001071846973900342640107770214858928188419765628151478620236042882657992902
n3= 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147#全位数
pbits = 512#缺省位数
kbits = pbits - p3.nbits() #nbits()位数
print (p3.nbits())
p3 = p3<< kbits
PR.<x> = PolynomialRing(Zmod(n3))f = x + p3
z = f.small_roots(X=2^kbits, beta=0.4)[0]
p = p3 + z
print ("p: ", hex(int(p)))
assert n3 % p == 0
此代码需在 SageMath 环境中运行
得到完整的p后后面只需要正常的RSA求解即可,脚本如下
import libnum
c3 = 59213696442373765895948702611659756779813897653022080905635545636905434038306468935283962686059037461940227618715695875589055593696352594630107082714757036815875497138523738695066811985036315624927897081153190329636864005133757096991035607918106529151451834369442313673849563635248465014289409374291381429646
e3 = 65537
n3 = 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147
p3 = int("0xda5f14bacd97f5504f39eeef22af37e8551700296843e536760cea761d334508003e01b886c0c69b4365759fb42a3faaf0c8888106bb9dbb1137769a37d191a7",16)
q3 = n3 // p3
d = libnum.invmod(e3,(p3-1)*(q3-1))
m3 =pow(c3,d,n3)
print(m3)
#m3 = 978430871477569051989776547659020359721056838635797362474311886436116962354292851181720060000979143571198378856012391742078510586927376783797757539078239088349758644144812898155106623543650953940606543822567423130350207207895380499638001151443841997176299548692737056724423631882
最后将三部分明文进行md5加密,脚本如下
from Crypto.Util.number import *
import hashlib
m1=267334379257781603687613466720913534310764480084016847281446486946801530200295563483353634338157
m2=4193305853284549103821195807609492624095031428085219879448342104337322945001387680236011960472296815293233144303730273979905837762067652913308898433728800864776794638198055607422503065410595894676740531680367227696622352026247676452540064020322619036125381146346603655445487695574824919137
m3=978430871477569051989776547659020359721056838635797362474311886436116962354292851181720060000979143571198378856012391742078510586927376783797757539078239088349758644144812898155106623543650953940606543822567423130350207207895380499638001151443841997176299548692737056724423631882
#将 m1, m2, m3分别转换为字节串
flag = long_to_bytes(m1)+long_to_bytes(m2)+long_to_bytes(m3)
#计算 MD5 并生成 flag
m = "NSSCTF{"+ hashlib.md5(flag).hexdigest() + "}"
print(m)
#NSSCTF{3943e8843a19149497956901e5d98639}
运行结果