RSA攻击:模数分解

目录

一、模数分解总览

        1.1直接分解法

        1.2费马分解与Pollard_rho分解

        1.3公约数分解

        1.4其他模数分解

二、实战特训

        2.1[黑盾杯 2020]Factor

       2.2[GWCTF 2019]babyRSA

      2.3[LitCTF 2023]yafu (中级)

        2.4[RoarCTF 2019]RSA

      2.5[CISCN 2022 西南]rsa

三、总结


一、模数分解总览

        1.1直接分解法

           在RSA的通信流程中,对外保密的是私钥,但是究其本质对外隐藏的是大素数P,Q。而正是大数分解难题的原因,使得即使暴露N,即PQ之积的值暴露,破解难度也依旧很大。所以,我们只需要掌握缺失的信息P,Q即可完成解密

          但是如果N值取的很小,我们通常可以进行暴力分解,从而获取P,Q。顺带一提,在工业中我们认为2048bit以上的N是安全的。但是,在CTF竞赛中,我们几乎不会遇到2048bit以上的素数分解。所以,这里我们可以放心使用。稍后,笔者会给处自己对与N很小的理解。

          使用条件:在阅读部分书籍的密码学(crypto)部分的解析,以及一些题目经验,大部分适合直接数模分解的N一般小于512bit。该使用条件,是笔者的拙见,欢迎大家在评论区讨论。

        1.2费马分解与Pollard_rho分解

          在1.1中我们提及了,如果N值很小,那么我们可以直接分解。但是如果N值大,我们将寸步难行。可是,这种难度在于直接分解,而不是利用部分数学技巧与原理。

          例如在费马分解中,当P,Q两个值过于接近,也就是P-Q的值很小。此时,我们就可以令A = (P + Q) / 2, B = (P - Q) / 2 则 N = A^2 - B^2。其中,在具体算法实现的过程中,因为P - Q很小,所以我们可以枚举爆破。而且根据 N = PQ,且N值一般已知,就有 A^2 = B^2 + N。

          而在Pollard_rho分解中,则恰恰相反。该分解说明当P,Q相差过大时,可以被暴力分解。从费马分解的角度说,如果P - Q过大,那么P + Q就会过小。因此可以枚举P + Q暴力破解。然而该分解方式有一定的数学原理(本菜狗没学原理,赶比赛就停在应用层面先)。

          Pollard算法的原理大体是通过某一种方式获取得到A,B值。计算p = gcd(a - b, n),直到p不为1,或者a,b出现循环。返回一个“因子”p。接着,我们可以递归的计算Pollard(p)与Pollard(n/p),值得一提得是我们p == n时,返回的就是n是一个质数退出。一般我们认为B = A^2 + 1。

          这个方法很美好,但是显示很骨感。这种分解方式建立于我们知道P - Q的状态。然而,现实和比赛中,P、Q都是被隐藏的,所以我们很难判断是否可以使用这种方式破解。SO!我们只能抱着尝试的方法使用该方法

        1.3公约数分解

          公约数分解一般是建立在多组信息(密文)在加密过程中,采取了相同的大素数P。因此,我们可以通过gcd来获取一个因此P,进而得知另外一个因子。

          使用条件:出现多组密文。

        1.4其他模数分解

          一般这种分解方式也是最难的,因为会考察选手的数学能力。也就是题目会给出一些额外的数学表达式,选手根据表达式合理爆破。或者我们可以使用factordb.com进行分解。但是当数字过大时,网站会显示补全,hhh。

          使用条件:当上述方式失效,或者题目给出额外的数学式子

二、实战特训

        2.1[黑盾杯 2020]Factor

          点击这里,跳转至题目

          在本道题中,我们获取得到了一下信息,如图所示。

          这道题有许多的尝试方法,如下:

          1.因为n比较小,可以直接分解n

          2. 因为e比较小以及给出了其他的数学关系,我们可以使用小加密明文爆破+数学关系判断。

          相对来讲,分解n更为简单。所以,我们优先尝试。注意:密码学更多的是尝试,而不是一眼定方法。使用yafu工具,我们获取一下因子。

          因此,我们可以编写一下代码段。

from Crypto.Util.number import *
import sympy
import primefac
from libnum import n2s
import gmpy2
import wienerAttackn = 3454083680130687060405946528826790951695785465926614724373
e = 3
c = 1347530713288996422676156069761604101177635382955634367208
# gcd(m, n) = 1p = 17100682436035561357
q = 17172929050033177661
r = 11761833764528579549phi = (q - 1) * (r - 1) * (p - 1)
d = primefac.modinv(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))

           但是,我们在运行时,发现代码报错。别急不是因为你错了,可能是因为出现了“假素数”,即(某一大素数 - 1) 是 e 的倍数。因此经过排查,发现(p - 1) % e == 0。因此剔除p。修改代码得到。

from Crypto.Util.number import *
import sympy
import primefac
from libnum import n2s
import gmpy2
import wienerAttackn = 3454083680130687060405946528826790951695785465926614724373
e = 3
c = 1347530713288996422676156069761604101177635382955634367208
# gcd(m, n) = 1p = 17100682436035561357
q = 17172929050033177661
r = 11761833764528579549phi = (q - 1) * (r - 1)
d = primefac.modinv(e, phi)
m = pow(c, d, q * r)
print(long_to_bytes(m))

          最后获取旗帜FLAG{3_RSA}。

       2.2[GWCTF 2019]babyRSA

          点击这里,跳转至题目

          根据题目附件,我们可以获取得到以下信息(未全部显示)。

          以及以下数学式:c1 = F1 + F2, c2 = F1^3 + F2^3。以及p < q。

          在这里我们获取到的信息是n值大概在2048bit。而且给出其他表达式,所以我们尝试其他数模分解法。

          首先,我们明确思路。我们需要获取c1, c2来计算得到F1、F2。然后,将F1、F2转职为字符串即可。而获取c1、c2我们需要获取p,q。所以,现在最大的难题在于p,q。在这里说明两种方式。

          方法1:关注到p,q是相邻的两个素数,如果你知道素数分布规律,即他们之间相差lnx。所以我们可以判断出 q - p 大约在1000。所以我们可以使用费马分解

          使用yafu分解得到以下结果。

         方法2(推荐掌握): 根据p < q的关系,我们可以判断出 n > p^2,所以sqrt(n) > p。所以,我们可以猜想 nextprime(sqrt(n)) == nextprime(p) == q。证明如下:

          n = n'^2 = pq = (n''^2 - d^2) ==> n'' = (p + q) / 2 > n' > p,也就是说 n' - p < q - p.建议画一个数轴理解。

import gmpy2
import sympyN=636585149594574746909030160182690866222909256464847291783000651837227921337237899651287943597773270944384034858925295744880727101606841413640006527614873110651410155893776548737823152943797884729130149758279127430044739254000426610922834573094957082589539445610828279428814524313491262061930512829074466232633130599104490893572093943832740301809630847541592548921200288222432789208650949937638303429456468889100192613859073752923812454212239908948930178355331390933536771065791817643978763045030833712326162883810638120029378337092938662174119747687899484603628344079493556601422498405360731958162719296160584042671057160241284852522913676264596201906163n = gmpy2.iroot(N, 2)[0]
q = sympy.nextprime(n)
p = n // q

          运行结果如下:其中1038 == q - p --> 验证素数分布,方法1

 

          两个方法没有优劣之分,知识方法二更贴合题意。方法一更快,但是需要我们判断p,q对应的数字。所以,按需对应选择。

          接下来获取c1,c2就简单了。

imoprt primefacphi = (p-1)*(q-1)
d = primefac.modinv(e, phi)c1 = powmod(m1, d, N)
c2 = powmod(m2, d, N)

        接下来获取F1,F2。构造二次方程x^2 - (F1 + F2)x + F1F2 = 0。使用c1,c2表示就为x^2 - c1x + (c1^2 - c2/c1)/3 = 0

A = gmpy2.mpz(1)
B = gmpy2.mpz(-c1)
C = gmpy2.mpz((c1*c1 - c2//c1)//3)
delta = gmpy2.mpz(gmpy2.iroot(B*B - 4*A*C,2)[0])
F1 = (-B - delta) // 2
F2 = (-B + delta) // 2flag1 = long_to_bytes(F1)
flag2 = long_to_bytes(F2)
print(flag1 + flag2, flag2 + flag1)

          得到旗帜FLAG{f709e0e2cfe7e530ca8972959a1033b2}

          当然你也可以使用sympy.solve来获取根。

      2.3[LitCTF 2023]yafu (中级)

        点击这里,跳转至题目

        这道题比较简单,题目就提示了使用yafu。一共会获取15个因子,这道题额外考察了欧拉函数的性质问题。解决代码如下。

p1=2151018733
p2=2201440207
p3=2315495107
p4=2585574697
p5=2719600579
p6=2758708999
p7=2767137487
p8=2906576131
p9=2923522073
p10=3354884521
p11=3355651511
p12=3989697563
p13=4021078331
p14=4044505687
p15=4171911923phi = (p1 - 1) * (p2 - 1) * (p3 - 1) * (p4 - 1) * (p5 - 1) * (p6 - 1) * (p7 - 1) * (p8 - 1) * (p9 - 1) * (p10 - 1) * (p11 - 1) * (p12 - 1) * (p13 - 1) * (p14 - 1) * (p15 - 1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))

        2.4[RoarCTF 2019]RSA

          点击这里,跳转至题目

         我们可以获取信息如下。

          在这里,我们知道P、Q可能相差过大,同时我们也获取了额外信息。所以我们可以尝试使用Pollard和其他数模分解法。

          尝试Pollard,发现预估等待时间 >= 1h。果断停止尝试。

          开始尝试其他数模分解。关注到有2019次方,所以枚举x,y的范围不会特别大,我们可以接受。

A =  2683349182678714524247469512793476009861014781004924905484127480308161377768192868061561886577048646432382128960881487463427414176114486885830693959404989743229103516924432512724195654425703453612710310587164417035878308390676612592848750287387318129424195208623440294647817367740878211949147526287091298307480502897462279102572556822231669438279317474828479089719046386411971105448723910594710418093977044179949800373224354729179833393219827789389078869290217569511230868967647963089430594258815146362187250855166897553056073744582946148472068334167445499314471518357535261186318756327890016183228412253724for x in range(1, 1000):for y in range(1, 1000):D = x % yif (D != 0) :f=(((y%x)**5)%D)**2019+y**316+(y+1)//xif (f == A) :print(x, y)break

        获得x = 2, y = 83

        然后我们关注到以下两个表达式:

          因此n = p * q > x*y*z^2, 也就是 n / x / y > z^2,那我们可以像2.2那样,获取q

n =  117930806043507374325982291823027285148807239117987369609583515353889814856088099671454394340816761242974462268435911765045576377767711593100416932019831889059333166946263184861287975722954992219766493089630810876984781113645362450398009234556085330943125568377741065242183073882558834603430862598066786475299918395341014877416901185392905676043795425126968745185649565106322336954427505104906770493155723995382318346714944184577894150229037758434597242564815299174950147754426950251419204917376517360505024549691723683358170823416757973059354784142601436519500811159036795034676360028928301979780528294114933347127x = 2
y = 83n1 = n // 166 #可以存放
q = sympy.nextprime(gmpy2.iroot(n1, 2)[0])
p = n // q
assert isPrime(q) and isPrime(p)print("OK") #确认步骤2正确
print(p, q)

        获得p,q后,我们就可以开始正是解码

c =  41971850275428383625653350824107291609587853887037624239544762751558838294718672159979929266922528917912189124713273673948051464226519605803745171340724343705832198554680196798623263806617998072496026019940476324971696928551159371970207365741517064295956376809297272541800647747885170905737868568000101029143923792003486793278197051326716680212726111099439262589341050943913401067673851885114314709706016622157285023272496793595281054074260451116213815934843317894898883215362289599366101018081513215120728297131352439066930452281829446586562062242527329672575620261776042653626411730955819001674118193293313612128e = 0x10001 # e = 65537
phi = (p - 1) * (q - 1)
d = primefac.modinv(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))

          获取旗帜FLAG{wm-l1l1ll1l1l1l111ll}

      2.5[CISCN 2022 西南]rsa

          点击这里,跳转至题目

          题目附件内容如下:

from Crypto.Util.number import *
import gmpy2flag = b'XXXXXXXX'
p1 = getPrime(700)
r1 = getPrime(700)
for i in range(10):q1 = 5*p1+i
n = p1*q1*r1
p3 = pow(p1,3,n)
q3 = pow(q1,3,n)print(p3)
print(q3)
'''
p3 = 29914513810588158800677413177910972738704129106546850855032986405861482276089830788972187432277517348644647399654780884571794069905291936470934226328931651386658328163535027343107140438177837479649822914209171476632450951930287641742344330471734177295804718555774395704231261550376220154493373703096062950390869299905383682611063374747752091585836452902373843865043412096365874638466683035848817858586173172058756256354758712684819253211761289032789542371351760915771791997388241121078055468403109260493642435791152671979552597191217179672328555740595434990908530985477314228867209314472001848844089467987561661918366232980944933533
q3 = 66208618374366130551979192465001581263127328176551695213970812805980115496523825511250542987452691413485117902772315362811067501379171731387904074565035353566976164797769439898266222919741874340315356585585077141595328441423323822407738375537476582506440045835592730211502035261968878999959340204806442390319739977816872969200022096331677277225467021553564212725120939434924481787524609852608476848761521446441776154400518315701988027274150425936061679275540502720782853648148897480117033152064922234451671636288396704170234613549011854618414776342798740690128675106027908639984431432591397555541420243824539205614036979987830125678
'''
P = getPrime(1024)
Q = getPrime(1024)
N = P * Q
E = 65537
lcm = gmpy2.lcm(P-1, Q-1)
e1 = gmpy2.invert(p1, lcm)
e2 = gmpy2.invert(r1, lcm)
m = bytes_to_long(flag)
c = pow(m, E, N)print(lcm)
print(c)
print(N)
'''
lcm = 4292158730589770192682795435047249488185453170529228019750042608688907718268448193363838203887391025871515871000364259326343790645215256385842265899206372365402431198699714374850409466996627163968391249416054093529090485677808301343590811445080871279796162536469847469761747058736980603093722710824453312207182881241846080117790728778291633761198069016865260030288832065807438020772711645648333908622890343009942617559434851450007195025869850769670769715654662127278293639938359741401336592219730356884542179574372134014927006215640945952229142436595334916765255426954857520777553915330597952622785359222832224632624
c = 4288727484183191191687364666620023549392656794153112764357730676861570386983002380982803054964588111708662498647767438881892355599604826306427809017097724346976778230464708540600157055782723189971534549543664668430013171469625043063261219462210251726207552819381767396148632877168530609902046293626355744288863460554297860696918890189350721960355460410677203131993419723440382095665713164422367291153108363066159712951217816814873413423853338021627653555202253351957999686659021298525147460016557904084617528199284448056532965033560516083489693334373695545423561715471204868795248569806148395196572046378679014697206
N  = 17168634922359080770731181740188997952741812682116912079000170434755630873073792773455352815549564103486063484001457037305375162580861025543369063596825489461609724794798857499401637867986508655873564997664216374116361942711233205374363245780323485119184650145879389879046988234947922412374890843297813248828996855478005656041814919367820336728271583686844991928889831691815821365423570311291064846736832327637944358854661523107817781673029406341843040857813841671405147146887291204140157388049394514390098066284975682117038362207142272098796924412602725857521665773622056312191400612944442008222587867782281556388669
'''

          这道题纯吓人,因为密文跟p3,q3没关系。所以我们不需要用到它。注意的是,这里phi用lcm来表示了。

d = primefac.modinv(E, lcm)
m = pow(c, d, n)
primt(long_to_bytes(m))

          获得FLAG{h3ll0_wo21d!}

三、总结

          在这里,涵盖了大部分的模数分解法的题目做法。我们分析了如何判断以及尝试的优先级。如何根据代码报错,进行实时的调整、排错。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/149403.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

使用idea 中的rest 将 git 合并部分分支代码到主分支

需求&#xff1a;当要将dev的分支中的部分代码合并到test分支时&#xff0c;又不想把dev的全部代码合并到test分支 例如dev分支已经提交了 demo1到4&#xff0c;到想把demo1-3的代码合并到test分支&#xff0c;demo4暂时不合并 可以使用idea的reset 功能满足以上需求 1首先切…

Seata 源码篇之AT模式启动流程 - 中 - 03

Seata 源码篇之AT模式启动流程 - 中 - 03 数据源代理会话代理锁定查询执行器本地事务提交本地事务回滚 更新执行器删除执行器插入执行器 小节 本系列文章: Seata 源码篇之核心思想 - 01Seata 源码篇之AT模式启动流程 - 上 - 02 数据源代理 当我们的数据源被代理后&#xff0c…

.Net开源迁移框架FluentMigrator的使用。

在实际的开发过程中&#xff0c;经常会遇到数据库结构变动&#xff0c;比如新增表、删除表&#xff1b;已有的表新增字段&#xff0c;删除字段&#xff1b;修改字段属性等等。而且需要开发环境、测试环境和生产环境进行同步。如果使用的是EF&#xff0c;还是挺方便的。而非EF环…

PyTorch入门之【tensor】

目录 tensor的创建tensor的相关信息tensor的运算 tensor的创建 1.手动创建 import torch test1torch.tensor([1,2,3])#一维时为向量 test2torch.tensor([[1,2,3]])#二维时为矩阵 test3torch.tensor([[[1,2,3]]])#三维及以上统称为tensor print(test1) print(test2) print(tes…

【Linux】线程详解完结篇——信号量 + 线程池 + 单例模式 + 读写锁

线程详解第四篇 前言正式开始信号量引例信号量的本质信号量相关的四个核心接口生产消费者模型用环形队列实现生产者消费者模型基于环形队列的生产消费模型的原理代码演示单生产者单消费者多生产者多消费者 计数器的意义 线程池基本概念代码 单例模式STL,智能指针和线程安全STL中…

文心一言 VS 讯飞星火 VS chatgpt (106)-- 算法导论10.1 4题

四、用go语言&#xff0c;重写 ENQUEUE 和 DEQUEUE 的代码&#xff0c;使之能处理队列的下溢和上溢。 文心一言&#xff1a; 在 Go 语言中&#xff0c;我们可以使用切片来实现队列。下面是如何实现 ENQUEUE 和 DEQUEUE 操作&#xff0c;同时处理队列的下溢和上溢的情况&#…

git提交代码的流程

1.拉取代码 当你进入了一家公司就需要拉去公司的代码进行开发,此时你的项目小组长会给你个地址拉代码, git clone 公司项目的地址 此时如果不使用了这个方式拉去代码,拉去的是master分支上的代码,但是很多数的情况下&#xff0c;公司的项目可能会在其它的分支上,因此到公…

经典算法-----汉诺塔问题

前言 今天我们学习一个老经典的问题-----汉诺塔问题&#xff0c;可能在学习编程之前我们就听说过这个问题&#xff0c;那这里我们如何去通过编程的方式去解决这么一个问题呢&#xff1f;下面接着看。 汉诺塔问题 问题描述 这里是引用汉诺塔问题源自印度一个古老的传说&#x…

Python3数据科学包系列(一):数据分析实战

Python3中类的高级语法及实战 Python3(基础|高级)语法实战(|多线程|多进程|线程池|进程池技术)|多线程安全问题解决方案 Python3数据科学包系列(一):数据分析实战 Python3数据科学包系列(二):数据分析实战 认识下数据科学中数据处理基础包: (1)NumPy 俗话说: 要学会跑需先…

<C++>类和对象-下

目录 一、构造函数的初始化 1. 构造函数体赋值 2. 初始化列表 2.1 概念 2.2 隐式类型转换式构造 2.3 explicit关键字 二、static静态成员 1. 概念 2. 特性 三、友元 1. 友元函数 2.友元类 四、内部类 1. 概念 五、匿名对象 1. const引用匿名对象 2. 匿名对象的隐式类型转换 总…

postgresql实现单主单从

实现步骤 1.主库创建一个有复制权限的用户 CREATE ROLE 用户名login # 有登录权限的角色即是用户replication #复制权限 encrypted password 密码;2.主库配置开放从库外部访问权限 修改 pg_hba.conf 文件 &#xff08;相当于开放防火墙&#xff09; # 类型 数据库 …

Swing程序设计(5)绝对布局,流布局

文章目录 前言一、布局管理器二、介绍 1.绝对布局2.流布局总结 前言 Swing窗体中&#xff0c;每一个组件都有大小和具体的位置。而在容器中摆放各种组件时&#xff0c;很难判断其组件的具体位置和大小。即一个完整的界面中&#xff0c;往往有多个组件&#xff0c;那么如何将这…

Unity如何实现TreeView

前言 最近有一个需求,需要实现一个TreeView的试图显示,开始我一直觉得这么通用的结构,肯定有现成的UI组件或者插件可以使用,结果,找了好久,都没有找到合适的插件,有两个效果差强人意。 最后在回家的路上突然灵光一闪,想到了一种简单的实现方式,什么插件都不用,仅使用…

基于虚拟同步发电机控制的双机并联Simulink仿真模型

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

1024 科学计数法

一.问题&#xff1a; 科学计数法是科学家用来表示很大或很小的数字的一种方便的方法&#xff0c;其满足正则表达式 [-][1-9].[0-9]E[-][0-9]&#xff0c;即数字的整数部分只有 1 位&#xff0c;小数部分至少有 1 位&#xff0c;该数字及其指数部分的正负号即使对正数也必定明确…

kafka集群工作机制

一、kafka在zookeeper上的元数据解释 kafka中的broker要选举Controller角色来管理整个kafka集群中的分区和副本状态。一个Topic下多个partition要选举Leader角色和客户端进行交互数据 Zookeeper客户端工具&#xff1a; prettyZoo。 下载地址&#xff1a;https://github.com/vr…

2023年R1快开门式压力容器操作证模拟考试题库及R1快开门式压力容器操作理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年R1快开门式压力容器操作证模拟考试题库及R1快开门式压力容器操作理论考试试题是由安全生产模拟考试一点通提供&#xff0c;R1快开门式压力容器操作证模拟考试题库是根据R1快开门式压力容器操作最新版教材&#…

润滑油泵控制(博途SCL源代码)

有关博途PLC定时器的各种使用方法请参考下面文章链接: 博途PLC IEC定时器编程应用(SCL语言)_博图 定时器-CSDN博客博途PLC定时器支持数据类型TIME 类型 ,写法支持T#2M10S 、T#10S等,时基是MS所以如果设置1M用 DINT数据类型就是60000,大部分HMI上数据类型很多不支持IEC的…

buuctf-[GXYCTF2019]禁止套娃 git泄露,无参数rce

用dirsearch扫一下&#xff0c;看到flag.php 访问一下没啥东西&#xff0c;使用githack python2 GitHack.py http://8996e81f-a75c-4180-b0ad-226d97ba61b2.node4.buuoj.cn/.git/查看index.php <?php include "flag.php"; echo "flag在哪里呢&#xff1f;…