RSA刷题系列(施工中)
1,共享素数
1)[闽盾杯 2021]decode
题目:
n1:
15228664629164509105936278301396170708905691970126305196584505186788860519598413718493859625462561931380632032431490419378905593909771649295663481782473029836321132574188559245931660756414915507930357509270674460219615256962333464689419869130366867401404262606367700782040693275068101244535880649261286041921882470460606034302142183971677715439862839410834231609821777031530457674591868138859358815039755085358568037032478394036448363183057305077227769673701227083943898736796552550712057417053897722979700329662099072959306298177351997084389916443815546425080826441671985030755256185725913397986385179516049927425591
n2:
28182418532443955655250943929828439725377604572088962537896240628709829618999901367131159759359513146864646169253348651905865895468151210748207509325666501438590382812326109260537618829438786609626137074778638549998280533912080708785604673270460635181275360847313985764185991865570533815651261638439461846512012164531330949433517277559149828806588070421852157781670188281908625986974579194819272643409859915715455134433970119584552350648013116998668938513347083566970423327936691885137812528912263666957628197241313496232397910546498542303925205356813548741679943691886217742767778075067797422624969714343428365022749
n3:
18355811159408154065817199279776805621878757240392366715869421799780946779485225342662736231980532326015283372375030686507311099745671828649419794838611580909610100636296701054995302819692794479292794716441442731393027118795245239019609474743841061251498233337758043553376098591254587406941205804917663153256036922860462415387926973551020540123742773938055950168965005226319984869124543783579240130888344231027912143592472823564266887957101575622993773291455143915263715932280728961208233983782906070719786115187115449430196335973764600533097718947377609348244073036523422892353195107093782201003551217830556519184839
e1:
65537
e2:
27751
e3:
65537
c1:
5368342382489380107251269030258282008067103595899117880173297169710980852124379736420135829984131832023988667774795223808420069001078159756328642298736759964890517323144475742861501409284299556459601222657540302786301791897975932176538612601162552795835603779910738886150925504885639254302406755008796950704938463132687940418772021406619622090999564746948113296328739593309200238996686945891130656599419832796482095787039339269564880847130379179831744694000940207887150388411084465949903406848727641093033681144598595895383689139227400553234701993087147186292040330589331703587405822925483701667354935313494938769206
c2:
21521672635651854919517759696514027081496995002884626306313384597771682621826437868933822942195279941318573525337109548152966094293276717095298929811895186384560362917891928656637913236676702009205642367801075592458101830488916914437754803979953027152373619293870115731171449223105986403604973873007338969000153480949617700626516389419935352576014084068271819009465242491467427642787306345049280205827574043586767133396458785487959251540831856187380154825027964867977651727983254127239427622549059938701125498520279503972702883327594442747467858234391945790597844344295786118320620376681461727686876948563884520137741
c3:
13940747781246179701167820858098775936269078279837839169409057305686612176371099274767269714494905207551971162649902129137425806839867713157472497469542260664882313041602553845621113546259276402534229231780532278276697961222319054833980226978574905974878218905613341365260453461080117407529132948986104191917111000811731784483944945364091757083949827612260904757837644538366763161154611658652020868326985526984718638276184626634240096213703958275241215175054246685206226179114590838833694648062135027841593419815101363262701960507235056752424778384286627997500871204804629047307688466887868894491042058198480775705486
初步思路:
分别给了 3个n,e,c, 共模攻击,广播攻击 一 一排除, 似乎就有三个对应的明文,
最近 看到一篇 博客,说道,给了多组n和c,不是广播攻击,可试试 n不互素
此处恰好为之
exp:
import libnum
e1 = 65537
e2 = 27751
e3 = 65537
n1 = 15228664629164509105936278301396170708905691970126305196584505186788860519598413718493859625462561931380632032431490419378905593909771649295663481782473029836321132574188559245931660756414915507930357509270674460219615256962333464689419869130366867401404262606367700782040693275068101244535880649261286041921882470460606034302142183971677715439862839410834231609821777031530457674591868138859358815039755085358568037032478394036448363183057305077227769673701227083943898736796552550712057417053897722979700329662099072959306298177351997084389916443815546425080826441671985030755256185725913397986385179516049927425591
n2 = 28182418532443955655250943929828439725377604572088962537896240628709829618999901367131159759359513146864646169253348651905865895468151210748207509325666501438590382812326109260537618829438786609626137074778638549998280533912080708785604673270460635181275360847313985764185991865570533815651261638439461846512012164531330949433517277559149828806588070421852157781670188281908625986974579194819272643409859915715455134433970119584552350648013116998668938513347083566970423327936691885137812528912263666957628197241313496232397910546498542303925205356813548741679943691886217742767778075067797422624969714343428365022749
n3 = 18355811159408154065817199279776805621878757240392366715869421799780946779485225342662736231980532326015283372375030686507311099745671828649419794838611580909610100636296701054995302819692794479292794716441442731393027118795245239019609474743841061251498233337758043553376098591254587406941205804917663153256036922860462415387926973551020540123742773938055950168965005226319984869124543783579240130888344231027912143592472823564266887957101575622993773291455143915263715932280728961208233983782906070719786115187115449430196335973764600533097718947377609348244073036523422892353195107093782201003551217830556519184839
c1 = 5368342382489380107251269030258282008067103595899117880173297169710980852124379736420135829984131832023988667774795223808420069001078159756328642298736759964890517323144475742861501409284299556459601222657540302786301791897975932176538612601162552795835603779910738886150925504885639254302406755008796950704938463132687940418772021406619622090999564746948113296328739593309200238996686945891130656599419832796482095787039339269564880847130379179831744694000940207887150388411084465949903406848727641093033681144598595895383689139227400553234701993087147186292040330589331703587405822925483701667354935313494938769206
c2 = 21521672635651854919517759696514027081496995002884626306313384597771682621826437868933822942195279941318573525337109548152966094293276717095298929811895186384560362917891928656637913236676702009205642367801075592458101830488916914437754803979953027152373619293870115731171449223105986403604973873007338969000153480949617700626516389419935352576014084068271819009465242491467427642787306345049280205827574043586767133396458785487959251540831856187380154825027964867977651727983254127239427622549059938701125498520279503972702883327594442747467858234391945790597844344295786118320620376681461727686876948563884520137741
c3 = 13940747781246179701167820858098775936269078279837839169409057305686612176371099274767269714494905207551971162649902129137425806839867713157472497469542260664882313041602553845621113546259276402534229231780532278276697961222319054833980226978574905974878218905613341365260453461080117407529132948986104191917111000811731784483944945364091757083949827612260904757837644538366763161154611658652020868326985526984718638276184626634240096213703958275241215175054246685206226179114590838833694648062135027841593419815101363262701960507235056752424778384286627997500871204804629047307688466887868894491042058198480775705486
p1 = libnum.gcd(n1,n2)
p2 = libnum.gcd(n2,n3)
q1 = n1//p1
q2 = n2 //p1
q3 = n3// p2
phi_1 = (p1-1)*(q1-1)
phi_2 = (p1-1)*(q2-1)
phi_3 = (p2-1)*(q3-1)
d1 = libnum.invmod(e1,phi_1)
d2 = libnum.invmod(e2,phi_2)
d3 = libnum.invmod(e3,phi_3)
print(libnum.n2s(pow(c1,d1,n1)))
print(libnum.n2s(pow(c2,d2,n2)))
print(libnum.n2s(pow(c3,d3,n3)))
# b"hahaha, you've got the flag didn't you !the front part is :flag{G00d_w4"
# b"hahaha, you've got the flag didn't you !the middle part is :y_tO_cR"
# b"hahaha, you've got the flag didn't you !the last part is :4ck_RS4}"
# flag{G00d_w4y_tO_cR4ck_RS4}
2,rabin算法
1)[HGAME 2023 week2]Rabin
题目源码:
from Crypto.Util.number import *
def gen_key(kbits):
while True:
p = getPrime(kbits)
q = getPrime(kbits)
if p % 4 == 3 and q % 4== 3:
break
return p, q
p ,q = gen_key(256)
flag = open("flag", 'rb').read()
pt = bytes_to_long(flag)
c = pow(pt, 2, p*q)
print(f"p={p}\nq={q}")
print(f"c={hex(c)[2:]}")
"""
p=65428327184555679690730137432886407240184329534772421373193521144693375074983
q=98570810268705084987524975482323456006480531917292601799256241458681800554123
c=4e072f435cbffbd3520a283b3944ac988b98fb19e723d1bd02ad7e58d9f01b26d622edea5ee538b2f603d5bf785b0427de27ad5c76c656dbd9435d3a4a7cf556
"""
p % 4 == 3 and q % 4== 3
exp:
from gmpy2 import *
import libnum
p=65428327184555679690730137432886407240184329534772421373193521144693375074983
q=98570810268705084987524975482323456006480531917292601799256241458681800554123
c=4086661358212073245252744496322167481491672871949606958127237667510352936336492238168574196919178461270299415887662858793221972137767350873928701793072470
n = p*q
inv_p = invert(p, q)
inv_q = invert(q, p)
mp = pow(c, (p+1)//4, p)
mq = pow(c, (q+1)//4, q)
a = (inv_p * p * mq + inv_q * q * mp) % n
b = n - int(a)
c = (inv_p * p * mq - inv_q * q * mp) % n
d = n - int(c)
#因为rabin 加密有四种结果,全部列出。
aa=[a,b,c,d]
for i in aa:
print(i)
print(libnum.n2s(int(i)))
# b"hgame{That'5_s0_3asy_to_s@lve_r@bin}"
3,p高位攻击
如何辨别高位和低位?
一串数据,如 12345678, 前面为高位,即 1234 ,后面为 低位,即 5678 , 千万,百万,十万,万, 千,百,十,个 (个人见解,仅供参考)
知道的 p 高位为 p 的位数的约 1/2 时即可用 下面脚本
#Sage
from sage.all import *
n =
p4 =
#p去0的剩余位
e =
pbits = 1024
kbits = pbits - p4.nbits()
print(p4.nbits())
p4 = p4 << kbits # 左移kbits位,即再p4二进制后加444个0
PR.<x> = PolynomialRing(Zmod(n))
f = x + p4
roots = f.small_roots(X=2^kbits, beta=0.4)
#经过以上一些函数处理后,n和p已经被转化为10进制
if roots:
p = p4+int(roots[0])
print("n: "+str(n))
print("p: "+str(p))
print("q: "+str(n//p))
import libnum,gmpy2
n =
e =
c =
p0 =
nbits = int(n).bit_length()
print(nbits)
p0bits = int(p0).bit_length()
print(p0bits)
p_high = p0
while int(p_high).bit_length()<(nbits//2):
p_high *=10
print(p_high)
PR.<x> = PolynomialRing(Zmod(n))
f = p_high+x
x = f.small_roots(X=2^(nbits//2-p0bits),beta=0.4)
p = p_high+int(x[0])
print(p)
q = n//p
d = int(gmpy2.invert(e,(p-1)*(q-1)))
m = int(pow(c,d,n))
flag = libnum.n2s(m)
print(flag)
PR.<x> = PolynomialRing(Zmod(n)) 1)
f = p_high+x 2)
x = f.small_roots(X=2^kbits,beta=0.4) 3)
p = p_high+int(x[0]) 4)
1)中Zmod(n) 中的 n 的和 2)p_high 似乎有一定关系,如 p是n的因子, f 这个多项式 相当于 p 的表达式 ,
p = p_high + x[0] , x[0] 为p的低位,p_high为p的高位 ,所以 位数 要对齐才能相加,
办法便是高位后面补0
x = f.small_roots(X=2^kbits,beta=0.4) ,其中X表示求解根的上界 , kbits 为 p 未知的二进制位数, x为 要求的 p的低位,即未知的部分
1)p>>400 ,
2)(p>>400) << 400 ,
3)p<< 400
1)是右移400位,可以理解为除去2^400,这个除是只保留整数的
2)先把低400位抹去,然后再补上400个0
3)是乘上2^400,即直接在二进制后面添400个0
举个例子
二进制数据p=11111111,
p>>4=00001111
(p>>4)<<4 = 11110000
直接上题
1)已知p的高位,求低位
题目源码:
from secrets import flag
from Crypto.Util.number import *
p = getPrime(1024)
q = getPrime(1024)
n = p*q
e = 65537
m = bytes_to_long(flag)
c = pow(m,e,n)
print('n =', n)
print('c =', c)
print('p0 =', ((p>>128)<<128))
# n = 12722276084782012506939748218137061976694333623308770803193278921311358642857520720238223717188895787376761058057320570031791633540549052360890626849683959794619430207976509336964838302913532815872846936103400538093765972176693960613553754981804951861018999147210521057815783304998144581807982126753283124281516688846477783545704858051397854514128591265938874177108889498151756070102637171159497913559176230984485047937009449456335164657258487948113487961895079102836099947427765851897399603733885367848305266219390271858890481731238036781050541110612526113637880146841891893392904381138771618976655066294938275191591
# c = 7016802271682704586027412586496213357494728781654536670879262263911645812024904159932204545849316301445405237966933240237035426118442003499546014556123485534516682277683392394418823209992176414301314576069643211825678886511259850322068086838470004809816539278374905405029448429356654864943156018053547494263664714952593505357117355251742922245508277007069593675629222770814317602710615647062020095140444497647478051326857816298790397174877223117345612840890905447851689835046066164443064435495141117872095457539285213399905708851752673701650986197704683439495235659865937503527178246189185724246027890778434827868479
# p0 = 121612618057439377491893234820394610861816815559052233952438700644930219565204914707604533201740057532331014637555250302342831261394993528125583478630623993361944114671033382653887624385660705353904988324932092635052885387222723368916634052933090217574600695084708857274271614116870074627080278200070403260416
((p>>128)<<128))
看到这个,便知是 p高位攻击 ,基础的那种,可直接带入写好的脚本
kibts = 128
exp:
# sage
import libnum,gmpy2
n = 12722276084782012506939748218137061976694333623308770803193278921311358642857520720238223717188895787376761058057320570031791633540549052360890626849683959794619430207976509336964838302913532815872846936103400538093765972176693960613553754981804951861018999147210521057815783304998144581807982126753283124281516688846477783545704858051397854514128591265938874177108889498151756070102637171159497913559176230984485047937009449456335164657258487948113487961895079102836099947427765851897399603733885367848305266219390271858890481731238036781050541110612526113637880146841891893392904381138771618976655066294938275191591
c = 7016802271682704586027412586496213357494728781654536670879262263911645812024904159932204545849316301445405237966933240237035426118442003499546014556123485534516682277683392394418823209992176414301314576069643211825678886511259850322068086838470004809816539278374905405029448429356654864943156018053547494263664714952593505357117355251742922245508277007069593675629222770814317602710615647062020095140444497647478051326857816298790397174877223117345612840890905447851689835046066164443064435495141117872095457539285213399905708851752673701650986197704683439495235659865937503527178246189185724246027890778434827868479
p0 = 121612618057439377491893234820394610861816815559052233952438700644930219565204914707604533201740057532331014637555250302342831261394993528125583478630623993361944114671033382653887624385660705353904988324932092635052885387222723368916634052933090217574600695084708857274271614116870074627080278200070403260416
e = 65537
nbits = int(n).bit_length()
print(nbits)
p0bits = int(p0).bit_length()
print(p0bits)
p_high = p0
while int(p_high).bit_length()<(nbits//2):
p_high *=10
print(p_high)
PR.<x> = PolynomialRing(Zmod(n))
f = p_high+x
x = f.small_roots(X=2^128,beta=0.4)
p = p_high+int(x[0])
print(p)
q = n//p
d = int(gmpy2.invert(e,(p-1)*(q-1)))
m = int(pow(c,d,n))
flag = libnum.n2s(m)
print(flag)
# b'flag{W0W_y0u_rea1ly_go0d_at_us3_s4g3!}'
2)已知p的高位,低位,求中间位
可参考:(67条消息) CTF-RSA已知高低位的攻击_rsa已知低位攻击_villons946的博客-CSDN博客
题目:
from secret import flag
from Crypto.Util.number import *
p, q = getPrime(1024), getPrime(1024)
N = p * q
p0 = p ^ (bytes_to_long(flag)<<444)
m = bytes_to_long(flag)
c = pow(m, 65537, N)
print(len(flag))
print('c=',c)
print('N=',N)
print('p0=',p0)
# 54
# c= 6187845844052645335477666563187579997555293403110620879123121166924703361821847984760733842049752886698011561451715570810292323756091403783920480396052120046379755571530451812078574368413924390017994278703794257118954968480994077586245800902748815905644287545189605031883291488844527496906890127546594960138582150272568163575590734246290813150131949296550974206595456421136190026954855755623761557179760444906148376433584795779131477110538212742401420633087881506416368853221110426491868881029814841479615979710066371796507692025126150957315754738584387325388998533227577023142894876376702128870643448600352603905149
# N= 14195810221536708489210274086946022255792382922322850338983263099316341767896809249586174293795778082892237356582757544364274847341220303582304283372889068290282580493623042441421715338444710303281638639785784613434328659529884972238348336971186339482788748316527376410510261228354155806341136524162787121212184386900663470590652770503564816948407257603737938414126069053610568675347826390537145556511048774030823322301932088595499671755944744816524811272617200683384649389274196659297432212847319503330409792704612575414010711158873031786577877685578976140462539734553598745329712188216200905451774357282278403189943
# p0= 111984935426070810628244029907949697819351004665202173622240566580193974673163315128983603277856218378729883402496424467491406698035050254407170555432448523469880166015507303737468316933545613178461925283040643344197452758878116752692499745309765526523083790825015522124083482964296662782850606081657447935191
p0 = p ^ (bytes_to_long(flag)<<444)
from Crypto.Util.number import bytes_to_long
a = b'a'*54
print(a)
print(bytes_to_long(a).bit_length())
# b'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
# 431
p 是1024bit的,flag是431bit的,flag<<444 ,相当于在其二进制后添444个0,即875bit
异或 ^ 异或 : 相同为0,不同为1 ,任何二进制数与零异或,都会等于其本身
所以p的后444位是不变的,即知道 p_low 444位
1024-875=149 , 所以 异或 时 p的高149位没有数与其异或,或者说,高位补0异或,同理,即p_high 已知149位
p_high 为p0 二进制的前149位,p_low为p0二进制的最后444位,
mm 为 m 的前431位(不算0b) ,因为 m<< 444, 最后444位全是0
exp:
import libnum, gmpy2
c= 6187845844052645335477666563187579997555293403110620879123121166924703361821847984760733842049752886698011561451715570810292323756091403783920480396052120046379755571530451812078574368413924390017994278703794257118954968480994077586245800902748815905644287545189605031883291488844527496906890127546594960138582150272568163575590734246290813150131949296550974206595456421136190026954855755623761557179760444906148376433584795779131477110538212742401420633087881506416368853221110426491868881029814841479615979710066371796507692025126150957315754738584387325388998533227577023142894876376702128870643448600352603905149
N= 14195810221536708489210274086946022255792382922322850338983263099316341767896809249586174293795778082892237356582757544364274847341220303582304283372889068290282580493623042441421715338444710303281638639785784613434328659529884972238348336971186339482788748316527376410510261228354155806341136524162787121212184386900663470590652770503564816948407257603737938414126069053610568675347826390537145556511048774030823322301932088595499671755944744816524811272617200683384649389274196659297432212847319503330409792704612575414010711158873031786577877685578976140462539734553598745329712188216200905451774357282278403189943
p0= 111984935426070810628244029907949697819351004665202173622240566580193974673163315128983603277856218378729883402496424467491406698035050254407170555432448523469880166015507303737468316933545613178461925283040643344197452758878116752692499745309765526523083790825015522124083482964296662782850606081657447935191
e = 65537
p_high =(p0>>(431+444))<<(431+444)
p_low = p0%(2^444)
PR.<x> = PolynomialRing(Zmod(N))
f = p_high+x*2^444+p_low
f = f.monic()
x = f.small_roots(X=2^flag_len, beta=0.4)
p = int(p_high+x[0]*2^444+p_low)
q = N//p
d = int(gmpy2.invert(e, (p-1)*(q-1)))
m = int(pow(c, d, N))
print(libnum.n2s(m))
# flag{816b78c555fc864d2f521b13bc9d6e932e9f5cbe511112df}
已知p的高位和低位,求p的中间位 和 p的高位攻击差不多,区别于此
f = p_high+x*2^444+p_low