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
"""
c = pow(pt,2,p*q)    =>  e = 2
 
常规解法试一遍,不行   ,  e和phi 不互素了  , 可 e= 2 ,太小 ,e和phi不互素的解法不可行,此时,看向题目 -- Rabin  ,据此解题
 
rabin算法
特征:e=2  ,       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的高位和低位,求p的中间位

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

 

posted @ 2023-07-12 14:54  Wbuildings  阅读(482)  评论(2编辑  收藏  举报