SUSCTF_Crypto_large case_复现

  • DescriptionDescriptionDescription
  • AnalysisAnalysisAnalysis
    • GeteGet~eGet e
    • GetplaintGet~plaintGet plaint
    • NecessaryMajorizationNecessary~MajorizationNecessary Majorization
      • FirstFirstFirst
      • SecondSecondSecond
  • SolvingcodeSolving~codeSolving code

keywords:keywords:keywords: e与欧拉函数非互质的RSA解密恢复e消除padding除去部分e的素因子

DescriptionDescriptionDescription

from Crypto.Util.number import *
from secret import e,messagedef pad(s):if len(s)<3*L:s+=bytes(3*L-len(s))return sL=128
p=127846753573603084140032502367311687577517286192893830888210505400863747960458410091624928485398237221748639465569360357083610343901195273740653100259873512668015324620239720302434418836556626441491996755736644886234427063508445212117628827393696641594389475794455769831224080974098671804484986257952189021223
q=145855456487495382044171198958191111759614682359121667762539436558951453420409098978730659224765186993202647878416602503196995715156477020462357271957894750950465766809623184979464111968346235929375202282811814079958258215558862385475337911665725569669510022344713444067774094112542265293776098223712339100693
r=165967627827619421909025667485886197280531070386062799707570138462960892786375448755168117226002965841166040777799690060003514218907279202146293715568618421507166624010447447835500614000601643150187327886055136468260391127675012777934049855029499330117864969171026445847229725440665179150874362143944727374907
n=p*q*rassert isPrime(GCD(e,p-1)) and isPrime(GCD(e,q-1)) and isPrime(GCD(e,r-1)) and e==GCD(e,p-1)*GCD(e,q-1)*GCD(e,r-1)
assert len(message)>L and len(message)<2*L
assert b'SUSCTF' in message
m=bytes_to_long(pad(message))c=pow(m,e,n)
print(c)
'''
2832775557487418816663494645849097066925967799754895979829784499040437385450603537732862576495758207240632734290947928291961063611897822688909447511260639429367768479378599532712621774918733304857247099714044615691877995534173849302353620399896455615474093581673774297730056975663792651743809514320379189748228186812362112753688073161375690508818356712739795492736743994105438575736577194329751372142329306630950863097761601196849158280502041616545429586870751042908365507050717385205371671658706357669408813112610215766159761927196639404951251535622349916877296956767883165696947955379829079278948514755758174884809479690995427980775293393456403529481055942899970158049070109142310832516606657100119207595631431023336544432679282722485978175459551109374822024850128128796213791820270973849303929674648894135672365776376696816104314090776423931007123128977218361110636927878232444348690591774581974226318856099862175526133892
'''

AnalysisAnalysisAnalysis

可以明显地看到

assert isPrime(GCD(e,p-1)) and isPrime(GCD(e,q-1)) and isPrime(GCD(e,r-1)) and e==GCD(e,p-1)*GCD(e,q-1)*GCD(e,r-1)

e∣p−1,q−1,r−1e|p-1,q-1,r-1e∣p−1,q−1,r−1;且eee是由eee与三个素数减一的最大公因数的乘积

这就意味着eee与ϕ(n)\phi(n)ϕ(n)不互素,那么即使我们知道了eee,也不能按照正常的RSA解密方式m≡cd(modn)m\equiv c^d\pmod nm≡cd(modn)求解

所以目前有两个难点,一是eee是未知大小的,二是如何在eee与ϕ(n)\phi(n)ϕ(n)非互质的情况下求解RSA


GeteGet~eGet e

p−1,q−1,r−1p-1,q-1,r-1p−1,q−1,r−1都可以先分解程成一些较小的素数和一两个较大的整数(无法继续分解了)

下面以求得epepep为例

∵gcd(e,ϕ(n))≠1\because gcd(e,\phi(n))\neq1∵gcd(e,ϕ(n))​=1,且 $ t^{p-1}\equiv t^{\frac{ep\cdot(p-1)}{ep}} \equiv (t^{ep}\pmod p)^{\frac{p-1}{ep}}\equiv 1\pmod p $;(费马小定理)

其中ttt是任意一个不是ppp倍数的整数,epepep是eee和p−1p-1p−1的最大公因数

换而言之,中间的tep(modp)t^{ep}\pmod ptep(modp)可以用来替换成与密文ccc相关的式子以达到求得eee的目的

∵c≡me(modn)≡mep⋅eq⋅er(modp⋅q⋅r)\because c\equiv m^e\pmod n\equiv m^{ep\cdot eq\cdot er}\pmod {p\cdot q\cdot r}∵c≡me(modn)≡mep⋅eq⋅er(modp⋅q⋅r)

∴c(modp)≡(mep(modp))eq⋅er(modp)\therefore c\pmod p\equiv (m^{ep}\pmod p)^{eq\cdot er}\pmod p∴c(modp)≡(mep(modp))eq⋅er(modp)

这里只要是正确的epepep,把ccc和epepep代入费马小定理的式子中会同余于111

这就意味着我们只需要爆破出满足cp−1ep≡1(modp)c^{\frac{p-1}{ep}}\equiv 1\pmod pcepp−1​≡1(modp)的epepep即可

同理eqeqeq,ererer

实现代码

import primefac
for e_p in primefac.primefac(p-1):if pow(c%p,(p-1)//e_p,p) == 1 and e_p != 2:# print(e_p)break
for e_q in primefac.primefac(q-1):if pow(c%q,(q-1)//e_q,q) == 1 and e_q != 2:# print(e_q)break
for e_r in primefac.primefac(r-1):if pow(c%r,(r-1)//e_r,r) == 1 and e_r != 2:# print(e_r)break

GetplaintGet~plaintGet plaint

一般的想法是AMM算法,但是根据这道题的条件AMM算法计算时间可能有几个小时,这里根据官方wp介绍的更为快捷的算法来解题

算法来源:https://eprint.iacr.org/2020/1059.pdf

算法的相关证明以及扩展详情可见上述论文

该算法的运行时间与eee的大小成线性关系(所以之后我们需要缩小eee)

这里就介绍算法过程

Algorithm1Algorithm~1Algorithm 1

先令ϕ˙=ϕ(n)e\dot\phi=\frac{\phi(n)}{e}ϕ˙​=eϕ(n)​;g=1g=1g=1

循环g=g+1g=g+1g=g+1;gE≡gϕ˙(modN)g_E\equiv g^{\dot\phi}\pmod NgE​≡gϕ˙​(modN)

直到出现gE≠1g_E\neq 1gE​​=1的gEg_EgE​

Algorithm2Algorithm~2Algorithm 2

依旧令ϕ˙=ϕ(n)e\dot\phi=\frac{\phi(n)}{e}ϕ˙​=eϕ(n)​

计算d≡e−1(modϕ˙)d\equiv e^{-1}\pmod {\dot\phi}d≡e−1(modϕ˙​);a≡cd(modN)a\equiv c^d\pmod Na≡cd(modN)

判断aaa转换为字节/字符类型之后,是否有价值的信息(这里就是判断是否b'SUSCTF'在其中)

若没有,进行eee次循环,跳出循环的条件也是上述条件

循环体:a≡a⋅gE(modN)a\equiv a \cdot g_E \pmod Na≡a⋅gE​(modN)

最后满足条件的aaa就是flag

代码实现

# 算法一
phi = phi_n // e
g = 1
g_E = pow(g,phi,n)
while g_E == 1:g = g + 1g_E = pow(g,phi,n)
# print(g,g_E)# 算法二
d = gmpy2.invert(e,phi)
a = pow(c,d,n)
for _ in tqdm(range(now_e)):flag = a if b"SUSCTF" in long_to_bytes(flag):print(long_to_bytes(flag))breakelse:a = a * g_E % n

NecessaryMajorizationNecessary~MajorizationNecessary Majorization

FirstFirstFirst

在Algorithm2Algorithm~2Algorithm 2中需要进行eee次循环,而目前e=757*66553*5156273=259776235785533;肉眼可见的太大了,可能没几年跑不完

那就除去rrr来缩小eee,显然不能简单地在eee上除去rrr就完了,还需要对ccc,ϕ(n)\phi(n)ϕ(n)作改变

令ϕ(n)=(p−1)⋅(q−1)\phi(n)=(p-1)\cdot (q-1)ϕ(n)=(p−1)⋅(q−1);N=NrN = \frac{N}{r}N=rN​

由dr⋅er≡1(modϕ(n))d_{r}\cdot e_r\equiv 1\pmod {\phi(n)}dr​⋅er​≡1(modϕ(n))求得逆元drd_{r}dr​

∵c≡mer⋅ep⋅eq(modp⋅q⋅r)\because c\equiv m^{e_r\cdot e_p\cdot e_q}\pmod {p\cdot q\cdot r}∵c≡mer​⋅ep​⋅eq​(modp⋅q⋅r)

∴cdr≡(mer⋅dr)ep⋅eq(modN)\therefore c^{d_r}\equiv (m^{e_r\cdot d_r})^{e_p\cdot e_q}\pmod N∴cdr​≡(mer​⋅dr​)ep​⋅eq​(modN)

所以计算c≡cdr(modN)c\equiv c^{d_{r}}\pmod Nc≡cdr​(modN)得到的ccc即是eee变化后对应的ccc

SecondSecondSecond

在RSA加密过程中程序对明文作了填充,也就是pad()函数

仔细观察也就是简单在明文十六进制位上不断添000直到整体的十六进制位达到3⋅L3\cdot L3⋅L位

而且真实的明文长度处于$ L$到2⋅L2\cdot L2⋅L之间(此时mmm小于NNN)

assert len(message)>L and len(message)<2*L

也就是说,至少填充了LLL位的十六进制,而总共3⋅L3\cdot L3⋅L的十六进制位已经大于了NNN

也就意味着这样已经造成了明文丢失,且无法恢复明文

那么就需要把填充的十六进制位数消除,至少消去LLL位的十六进制(其余的填充位因为未知大小所以就不管了),因为2⋅L2\cdot L2⋅L的十六进制位是小于NNN的,可以就此恢复明文

仔细观察pad()函数

def pad(s):if len(s)<3*L:s+=bytes(3*L-len(s))return s

实际上我们使用二进制更多一些,这里1 byte是888个二进制位,那么实际有28⋅L2^{8\cdot L}28⋅L多余的数

原来的pad()函数相当于m=m⋅28⋅Lm=m\cdot 2^{8\cdot L}m=m⋅28⋅L;代入RSA加密之后,可以这样看

c≡cm⋅cpad≡cm⋅28⋅L⋅e(modN)c\equiv c_m\cdot c_{pad}\equiv c_m\cdot 2^{8\cdot L\cdot e}\pmod Nc≡cm​⋅cpad​≡cm​⋅28⋅L⋅e(modN)

那么为了消去pad的影响,我们直接乘上padding的逆元d=gmpy2.invert(pow(2,8*L*e,N),N)

其中,这里的eee和NNN可以是除去rrr之后的,也可以是除去rrr之前的

实现代码

c = c * gmpy2.invert(pow(2,8 * L * e,n),n) % n

SolvingcodeSolving~codeSolving code

from Crypto.Util.number import *
import gmpy2,primefac
from tqdm import tqdmL = 128
p = 127846753573603084140032502367311687577517286192893830888210505400863747960458410091624928485398237221748639465569360357083610343901195273740653100259873512668015324620239720302434418836556626441491996755736644886234427063508445212117628827393696641594389475794455769831224080974098671804484986257952189021223
q = 145855456487495382044171198958191111759614682359121667762539436558951453420409098978730659224765186993202647878416602503196995715156477020462357271957894750950465766809623184979464111968346235929375202282811814079958258215558862385475337911665725569669510022344713444067774094112542265293776098223712339100693
r = 165967627827619421909025667485886197280531070386062799707570138462960892786375448755168117226002965841166040777799690060003514218907279202146293715568618421507166624010447447835500614000601643150187327886055136468260391127675012777934049855029499330117864969171026445847229725440665179150874362143944727374907
c = 2832775557487418816663494645849097066925967799754895979829784499040437385450603537732862576495758207240632734290947928291961063611897822688909447511260639429367768479378599532712621774918733304857247099714044615691877995534173849302353620399896455615474093581673774297730056975663792651743809514320379189748228186812362112753688073161375690508818356712739795492736743994105438575736577194329751372142329306630950863097761601196849158280502041616545429586870751042908365507050717385205371671658706357669408813112610215766159761927196639404951251535622349916877296956767883165696947955379829079278948514755758174884809479690995427980775293393456403529481055942899970158049070109142310832516606657100119207595631431023336544432679282722485978175459551109374822024850128128796213791820270973849303929674648894135672365776376696816104314090776423931007123128977218361110636927878232444348690591774581974226318856099862175526133892
n = p * q * r# 恢复e
for e_p in primefac.primefac(p-1):if pow(c%p,(p-1)//e_p,p) == 1 and e_p != 2:# print(e_p)break
for e_q in primefac.primefac(q-1):if pow(c%q,(q-1)//e_q,q) == 1 and e_q != 2:# print(e_q)break
for e_r in primefac.primefac(r-1):if pow(c%r,(r-1)//e_r,r) == 1 and e_r != 2:# print(e_r)break
e = e_p * e_q * e_r
# print(e_p,e_q,e_r)
phi_n = (p - 1) * (q - 1) * (r - 1)
# print(e)# 消除L位的十六进制的padding(在删除r之前)
c = c * gmpy2.invert(pow(2,8 * L * e,n),n) % n# 缩小e:删除r以及更改各个指标的受r的影响
e = e // e_r
phi_n_without_r = (p - 1) * (q - 1)
n = n // r
d1 = gmpy2.invert(e_r,phi_n_without_r)
c = pow(c,d1,n)# 在删除r后消除padding
# c = c * gmpy2.invert(pow(2,8 * L * now_e,n),n) % n# 算法一
phi = phi_n_without_r // e
g = 1
g_E = pow(g,phi,n)
while g_E == 1:g = g + 1g_E = pow(g,phi,n)
# print(g,g_E)# 算法二
d = gmpy2.invert(e,phi)
a = pow(c,d,n)
for _ in tqdm(range(e)):flag = a if b"SUSCTF" in long_to_bytes(flag):print()print(long_to_bytes(flag))breakelse:a = a * g_E % n

最后得到flag

SUSCTF_Crypto_large case_复现相关推荐

  1. Facebook 发布深度学习工具包 PyTorch Hub,让论文复现变得更容易

    近日,PyTorch 社区发布了一个深度学习工具包 PyTorchHub, 帮助机器学习工作者更快实现重要论文的复现工作.PyTorchHub 由一个预训练模型仓库组成,专门用于提高研究工作的复现性以 ...

  2. 【目标检测】yolo系列:从yolov1到yolov5之YOLOv1详解及复现

    检测器通常能够被分为两类,一类是two-stage检测器,最具代表的为faster R-CNN:另一类是one-stage检测器,包括YOLO,SSD等.一般来说,two-stage检测器具有高定位和 ...

  3. CV算法复现(分类算法2/6):AlexNet(2012年 Hinton组)

    致谢:霹雳吧啦Wz:https://space.bilibili.com/18161609 目录 致谢:霹雳吧啦Wz:https://space.bilibili.com/18161609 1 本次要 ...

  4. 【神经网络】(17) EfficientNet 代码复现,网络解析,附Tensorflow完整代码

    各位同学好,今天和大家分享一下如何使用 Tensorflow 复现 EfficientNet 卷积神经网络模型. EfficientNet 的网络结构和 MobileNetV3 比较相似,建议大家在学 ...

  5. 【神经网络】(16) MobileNetV3 代码复现,网络解析,附Tensorflow完整代码

    各位同学好,今天和大家分享一下如何使用 Tensorflow 构建 MobileNetV3 轻量化网络模型. MobileNetV3 做了如下改动(1)更新了V2中的逆转残差结构:(2)使用NAS搜索 ...

  6. 【神经网络】(15) Xception 代码复现,网络解析,附Tensorflow完整代码

    各位同学好,今天和大家分享一下如何使用 Tensorflow 构建 Xception 神经网络模型. 在前面章节中,我已经介绍了很多种轻量化卷积神经网络模型,感兴趣的可以看一下:https://blo ...

  7. 【神经网络】(14) MnasNet 代码复现,网络解析,附Tensorflow完整代码

    各位同学好,今天和大家分享一下如何使用 Tensorflow 复现谷歌轻量化神经网络 MnasNet  通常而言,移动端(手机)和终端(安防监控.无人驾驶)上的设备计算能力有限,无法搭载庞大的神经网络 ...

  8. 【神经网络】(13) ShuffleNetV2 代码复现,网络解析,附Tensorflow完整代码

    各位同学好,今天和大家分享一下如何使用 Tensorflow 复现轻量化神经网络 ShuffleNetV2. 为了能将神经网络模型用于移动端(手机)和终端(安防监控.无人驾驶)的实时计算,通常这些设备 ...

  9. 【神经网络】(11) 轻量化网络MobileNetV1代码复现、解析,附Tensorflow完整代码

    各位同学好,今天和大家分享一下如何使用 Tensorflow 复现轻量化神经网络模型 MobileNetV1.为了能将神经网络模型用于移动端(手机)和终端(安防监控.无人驾驶)的实时计算,通常这些设备 ...

最新文章

  1. Js中的callback机制
  2. 仿ireader书架
  3. 使用FakeAsync对Angular异步代码进行单元测试
  4. python中return和printf的区别_Python格式化输出:%s和format()用法比较
  5. 正则表达式的捕获性分组/反向引用
  6. 锦标赛排序、洪水填充算法、平衡规划
  7. Python爬虫连载16-OCR工具Tesseract、Scrapt初步
  8. C#中的表达式与运算符
  9. maven下载安装环境配置
  10. 证券交易1-交易系统简介
  11. 从零开始研发GPS接收机连载——4、GPS模拟器数据采集验证
  12. Inav Configurator给F4刷固件进入不了DFU
  13. CAD中属性编辑操作——对象属性
  14. MAC下如何解压.bin文件
  15. 杭州电子科技大学ACM-1093
  16. 清华大学计算机吴教授,清华大学计算机系教授吴文虎到我校讲学
  17. 目标定位算法(三)之基于角度的定位算法
  18. Qt 开发使用VSCode
  19. 开源物联网监控告警平台JAVA开发
  20. 侵犯计算机软件著作权的行为,侵犯计算机软件著作权的行为有哪些?

热门文章

  1. CentOS 7服务器安装brook和bbr加速
  2. java面试题集中营-02集合
  3. 1.JAVA编程算体积
  4. Python3 菜鸟教程 笔记3 -- 列表和元组
  5. Hit the Lottery
  6. 普源1GHz频谱分析仪DSA710
  7. 国内第二波信息化wave:国家智能电网标准出台-《智能电网技术标准体系规划》...
  8. 40岁老同事,毛骨悚然的创业之路
  9. 东北大学计算机学院李捷,计算机与通信工程学院第四次学生代表大会暨第十届院属学生组织换届表彰大会顺利举行...
  10. 北京 | 深度学习与人工智能研修