有关RSA的一道题

有关RSA的一道题

因为中间去考研去了,导致好久没有更新了,结果果然没有上岸。中间大概有了一年多的空白期没有去搞技术,目前也是工作了有三个月了,因为保密不能将工作上的一些漏洞发出来,只能发一些自己空闲时间学习的一些东西。我对于 rsa 加密的程度仅停留在书本上的基本概念,还没有真正去做过一道题,下午闲来无事在看雪逛了逛看到了一道有意思的题,就去做了一下。

简单了解一下rsa加密

加密 C=p^e(mod n)

解密 P=c^d(mod n)

e、d之间的关系:

p*q=n

phin=(q-1)*(p-1) //也就是计算欧拉函数

e*d= 1 (mod phin)

题目

from Crypto.Util.number import *
import gmpy2
from jx2023 import flag, N, E
 
p = getPrime(1024)
q = getPrime(1024)
n = p*q
e1 = 65537
m = bytes_to_long(flag)
flagenc = pow(m, e1, n)
print("n is %d"%n)
print("flagenc is %d"%flagenc)
 
e2 = getPrime(122)
d2 = gmpy2.invert(e2,(p-1)*(q-1))
 
c1 = pow(e2, 17, n)
print("c1 is %d"%c1)
c2 = pow(d2, E, N)
print("N is %d"%N)
print("E is %d"%E)
print("c2 is %d"%c2)
 
# n is 8783117353228609820060025773720048836109116296720444291318682193328216575376903671782151675801584925066872219021319381163804239505579013818679255656402117567158378369967703317919205364480806143209934093723468591544792794708122025724968669241594029740047941933910596214170603520800531302474255823072859735679699558933009869241259760910402379740926512037606096020308081609477145816657118917642443176163860564823645522254412566891344745856141731910712040298787696382973824645074768059896153817964229975814742137600918515702471008251376697190058997187350022140633621955761877009643524289144711721902192261617574896449017
 
# flagenc is 1832021020586052459314800741399454951500982061634041208695770794636942946870944684781204845687614819955481692885982545657535952608100558061853098768890990198808258902800083671402999197944855469054517686346352932015639347886120547093778527571008483890754044661117042113616196224634409728684137167049242919543742476300792865668127981523314258326046469003175979484948578219765126696355000799390683333335678236115175267218556919253045561467791607635318317825080003594243366362225620291777807071774013296604063473075790067769213249767073197915283384750139985842145668772180552896467043807903712438253502782564391233381742
 
# c1 is 7501185876834032332235110133210399479682524972321262801050956129090974843598848916000280794969942298848478394986779571489577405391165372124215072990382219817624500948789393550575823082225944683449240150364401487955484843961943987266467050723988657081468393104862383181698999645914573683498375228946881234015678337769955671069215094086232377038727627179660862997067062391991524231807127953937881102711759932207432989764529075450526104070640765094626829603546052250863300827172150912585791552174463067989228539713261075253602907390439036055716154404417991482262846355144755622306307102084492476950657455416297047328320
 
# N is 29956031606905964747690208452463077877156885038545111351508842927295510069375356079358289621922278316223452695576175299757472345749152582617292471487006177231261463793638998998552474423214925625798531662484883149899251884707864709821973208465998076621327151198438158796296778838657562126343551661323471767755161686549607991960624754677443327266743771304424298446433734879681913848286620429175461870451099771965936783237191184798864363652633155779478727580408625494617809961465590055999661472563150275608218351797354628429061984878432442357241449134341597647749840966740944318445550768334070331490455379767889443973947
 
# E is 3527492693
 
# c2 is 11237333233288323887902003767693284822911839921763421974808265907264411495367936669799604082222415065052099486867383635886650443299459413288200494593477575168578514325691333043832168789236017314435940348619410775859032696755081680003338452277759483862961120696587307757666691557048088894021864124052243936836752825473836552342254367444581003605318145868368417247224184184040226260236268012375524575700053732026218766291274077482132408824236096242385408780811520890742688121731805867574680433796282417791570436991022839930635640379142355212121030479526679958801911687722402447690578345774902440346290388183936888977900

网友 hypersine 评论回复思路已经很明确了

N是一个不安全的大合数,可以用yafu快速分解得到P、Q,因此可以算出E对应的D,从而解密c2得到d2。题目中N的两个因数P、Q靠得太近了,两者之差未超过10000(实际是2214),所以很容易分解。

c1 = pow(e2, 17, n),但e2是一个122位的质数,因此e2^17应该有122 * 17 = 2074位,太接近于n的2048位。这里可以暴力破解,因为c1 = pow(e2, 17, n),所以存在k使得e2^17 == k * n + c1,这个k范围不大,不超过2^(2074 - 2048 + 1) = 2^27,自己写个程序穷举k就好,穷举到k * n + c1是一个完全17次方数就行,然后开17次方得到e2。
解一个简单的RSA题目-CTF对抗-看雪论坛-安全社区|非营利性质技术交流社区这篇文章写的很详细,跟着做了一下。

解题思路

求解e2

这是一道很经典的同幂攻击

同幂攻击的一般条件

  1. 密文公式 c=m^e mod n
  2. 公钥 e 很小

在这道题中

p = getPrime(1024)
q = getPrime(1024)
n = p*q
e2 = getPrime(122)
c1 = pow(e2, 17, n)

我们可以发现 122x17=2074 > 2048 且大的不多

为什么会有 122x17=2074 因为是 122 位二进制,所以 log⁡2(e2)≈122log2(e2),位长 e2 ^17 ≈2074

所以我们可以使用爆破得到 e2 ,因为 c1 = pow(e2, 17, n) 也就是 c1 = e2¹⁷ mod n

e2¹⁷=k*n +c1, 因为 k≈e2¹⁷/n 所以 k 的范围是 [1,2**26)。我们可以写一个爆破脚本

for k in range( 1, 2 ** 26 + 1 ) :
    candidate_e2  = gmpy2.iroot( c1 + k * n, 17 )
    if candidate_e2[1] :
        e2  = int( candidate_e2[0] )
        break

求解d2、phin、d1

因为我们最终的目标是

flagenc = pow(m, e1, n)

所以下面我们需要去求解一下 d1 是多少,但是求解 d1 需要知道 phin 欧拉值和 e1因为 e1*d1= 1 (mod phin)d1 = pow(e1, -1, phin)

d2 = gmpy2.invert(e2,(p-1)*(q-1))

发现d2 是使用 phin 生成。也就是说求出来 d2 在加上 爆破出的 e2 就能得到 phin

c2 = pow(d2, E, N)  //c2 ≡ d2^E (mod N) 

在只知道c2、N、E的情况下很难很难得到d2,这是因为rsa加密设计是基于离散对数困难问题设计的,但是这个N并不安全,可以使用yafu分解得到Q、P(下载地址https://sourceforge.net/projects/yafu/)当我们知道了HPIN后就可以直接得到D了,D = pow( E, -1, PHIN )进而得到d2

D=pow(E,-1,PHIN)
d2=pow(c2,D,N)

知道 e1,phin很容易得到 d1

d1=pow(e1,-1,phin)

使用 yafu 分解一下 N

C:\Users>yafu-x64 "factor(@)" -batchfile C:\Users\Desktop\python\trunk.txt

=== Starting work on batchfile expression ===

factor(29956031606905964747690208452463077877156885038545111351508842927295510069375356079358289621922278316223452695576175299757472345749152582617292471487006177231261463793638998998552474423214925625798531662484883149899251884707864709821973208465998076621327151198438158796296778838657562126343551661323471767755161686549607991960624754677443327266743771304424298446433734879681913848286620429175461870451099771965936783237191184798864363652633155779478727580408625494617809961465590055999661472563150275608218351797354628429061984878432442357241449134341597647749840966740944318445550768334070331490455379767889443973947)

fac: factoring 29956031606905964747690208452463077877156885038545111351508842927295510069375356079358289621922278316223452695576175299757472345749152582617292471487006177231261463793638998998552474423214925625798531662484883149899251884707864709821973208465998076621327151198438158796296778838657562126343551661323471767755161686549607991960624754677443327266743771304424298446433734879681913848286620429175461870451099771965936783237191184798864363652633155779478727580408625494617809961465590055999661472563150275608218351797354628429061984878432442357241449134341597647749840966740944318445550768334070331490455379767889443973947
fac: using pretesting plan: normal
fac: no tune info: using qs/gnfs crossover of 95 digits
div: primes less than 10000
fmt: 1000000 iterations
Total factoring time = 4.9468 seconds

factors found

P309 = 173078108398797693665135881829236075381385640386270681597614075449385160047192826549689858183180936639070064309925929218966667262650552855318783567546131862440848767306600252044834602371191453881522882233745590790067041490962165388372445595736465527512700919336312857203007896777270237470242797091626699715021
P309 = 173078108398797693665135881829236075381385640386270681597614075449385160047192826549689858183180936639070064309925929218966667262650552855318783567546131862440848767306600252044834602371191453881522882233745590790067041490962165388372445595736465527512700919336312857203007896777270237470242797091626699712807

ans = 1

eof; done processing batchfile

脚本

N=29956031606905964747690208452463077877156885038545111351508842927295510069375356079358289621922278316223452695576175299757472345749152582617292471487006177231261463793638998998552474423214925625798531662484883149899251884707864709821973208465998076621327151198438158796296778838657562126343551661323471767755161686549607991960624754677443327266743771304424298446433734879681913848286620429175461870451099771965936783237191184798864363652633155779478727580408625494617809961465590055999661472563150275608218351797354628429061984878432442357241449134341597647749840966740944318445550768334070331490455379767889443973947
P=173078108398797693665135881829236075381385640386270681597614075449385160047192826549689858183180936639070064309925929218966667262650552855318783567546131862440848767306600252044834602371191453881522882233745590790067041490962165388372445595736465527512700919336312857203007896777270237470242797091626699715021
Q=173078108398797693665135881829236075381385640386270681597614075449385160047192826549689858183180936639070064309925929218966667262650552855318783567546131862440848767306600252044834602371191453881522882233745590790067041490962165388372445595736465527512700919336312857203007896777270237470242797091626699712807
E=3527492693
e1=65537
PHIN=(Q-1)*(P-1)
D=pow(E,-1,PHIN)
d2=pow(c2,D,N)
phin=d2*e2-1
d1=pow(e1,-1,phin)

脚本

我们都已经得到了d1 ,那flag 也就不言而喻了

n = 8783117353228609820060025773720048836109116296720444291318682193328216575376903671782151675801584925066872219021319381163804239505579013818679255656402117567158378369967703317919205364480806143209934093723468591544792794708122025724968669241594029740047941933910596214170603520800531302474255823072859735679699558933009869241259760910402379740926512037606096020308081609477145816657118917642443176163860564823645522254412566891344745856141731910712040298787696382973824645074768059896153817964229975814742137600918515702471008251376697190058997187350022140633621955761877009643524289144711721902192261617574896449017

flagenc=1832021020586052459314800741399454951500982061634041208695770794636942946870944684781204845687614819955481692885982545657535952608100558061853098768890990198808258902800083671402999197944855469054517686346352932015639347886120547093778527571008483890754044661117042113616196224634409728684137167049242919543742476300792865668127981523314258326046469003175979484948578219765126696355000799390683333335678236115175267218556919253045561467791607635318317825080003594243366362225620291777807071774013296604063473075790067769213249767073197915283384750139985842145668772180552896467043807903712438253502782564391233381742
m = pow(flagenc, d1, n)
flag = Crypto.Util.number.long_to_bytes(m)

完整脚本如下

import gmpy2

import Crypto.Util.number
N = 29956031606905964747690208452463077877156885038545111351508842927295510069375356079358289621922278316223452695576175299757472345749152582617292471487006177231261463793638998998552474423214925625798531662484883149899251884707864709821973208465998076621327151198438158796296778838657562126343551661323471767755161686549607991960624754677443327266743771304424298446433734879681913848286620429175461870451099771965936783237191184798864363652633155779478727580408625494617809961465590055999661472563150275608218351797354628429061984878432442357241449134341597647749840966740944318445550768334070331490455379767889443973947

P=173078108398797693665135881829236075381385640386270681597614075449385160047192826549689858183180936639070064309925929218966667262650552855318783567546131862440848767306600252044834602371191453881522882233745590790067041490962165388372445595736465527512700919336312857203007896777270237470242797091626699715021
Q=173078108398797693665135881829236075381385640386270681597614075449385160047192826549689858183180936639070064309925929218966667262650552855318783567546131862440848767306600252044834602371191453881522882233745590790067041490962165388372445595736465527512700919336312857203007896777270237470242797091626699712807
c1 = 7501185876834032332235110133210399479682524972321262801050956129090974843598848916000280794969942298848478394986779571489577405391165372124215072990382219817624500948789393550575823082225944683449240150364401487955484843961943987266467050723988657081468393104862383181698999645914573683498375228946881234015678337769955671069215094086232377038727627179660862997067062391991524231807127953937881102711759932207432989764529075450526104070640765094626829603546052250863300827172150912585791552174463067989228539713261075253602907390439036055716154404417991482262846355144755622306307102084492476950657455416297047328320
n = 8783117353228609820060025773720048836109116296720444291318682193328216575376903671782151675801584925066872219021319381163804239505579013818679255656402117567158378369967703317919205364480806143209934093723468591544792794708122025724968669241594029740047941933910596214170603520800531302474255823072859735679699558933009869241259760910402379740926512037606096020308081609477145816657118917642443176163860564823645522254412566891344745856141731910712040298787696382973824645074768059896153817964229975814742137600918515702471008251376697190058997187350022140633621955761877009643524289144711721902192261617574896449017



for k in range(1, 2 ** 26 + 1):
    candidate_e2 = gmpy2.iroot(c1 + k * n, 17)
    if candidate_e2[1]:
        e2 = int(candidate_e2[0])
        break

print("e2:",e2)
PHIN=(P-1)*(Q-1)

print("PHIN:",PHIN)

E=3527492693
D=pow(E,-1,PHIN)
print("D:",D)
c2=11237333233288323887902003767693284822911839921763421974808265907264411495367936669799604082222415065052099486867383635886650443299459413288200494593477575168578514325691333043832168789236017314435940348619410775859032696755081680003338452277759483862961120696587307757666691557048088894021864124052243936836752825473836552342254367444581003605318145868368417247224184184040226260236268012375524575700053732026218766291274077482132408824236096242385408780811520890742688121731805867574680433796282417791570436991022839930635640379142355212121030479526679958801911687722402447690578345774902440346290388183936888977900
d2=pow(c2,D,N)
print("d2:",d2)
phin = d2 * e2 - 1
print("phin:",phin)
e1=65537
d1=pow( e1, -1, phin )
print("d1:",d1)

flagenc=1832021020586052459314800741399454951500982061634041208695770794636942946870944684781204845687614819955481692885982545657535952608100558061853098768890990198808258902800083671402999197944855469054517686346352932015639347886120547093778527571008483890754044661117042113616196224634409728684137167049242919543742476300792865668127981523314258326046469003175979484948578219765126696355000799390683333335678236115175267218556919253045561467791607635318317825080003594243366362225620291777807071774013296604063473075790067769213249767073197915283384750139985842145668772180552896467043807903712438253502782564391233381742

m = pow(flagenc, d1, n)

flag = Crypto.Util.number.long_to_bytes(m)
print("flah:",flag)


posted @ 2025-09-16 10:36  何思泊河  阅读(61)  评论(0)    收藏  举报