攻防世界Crypto OldDriver 和一堆它的“中国剩余定理”脚本

首先根据题目给到的一堆n、e和c,认为这里是在考低加密指数广播攻击(这个名词我不太能理解,直接当专有名词理解了......)。这里我参考了某些文章,发现存在以下情况时可使用低加密指数广播攻击:

首先你有多组模数n和密文c;这些密文c是由同一段明文m通过同一个很小的公钥指数e配合不同的模数n加密得来的。

(强调:你的明文m是唯一的。公钥指数e不仅唯一,而且还很小(具体多小我不知道,但是在我看来,最多是两位数))

而我们了解,RSA加密时涉及这样一条公式:

                                                        c=m^e (mod~n)

我们既然有多组n和c,就可以依据中国剩余定理来求解出m的e次方(“中国剩余定理”的作用),然后开e次方即可。

其实第一次接触这题,当知道需要“中国剩余定理”时我就不淡定了......但最后发现不会很难理解。

我当时靠这位大佬的博客理解清楚:(原理)中国剩余定理-CSDN博客 。(博客中的复杂算式在第一次看文章时可以暂且略过,但是等最后文章看完时推荐回过头来仔细研究(除了最后一张图,我认为))

理解清楚后,我当时编出了这样一段代码,结果成功地解决了“物不知其数”问题:

 #中国剩余定理脚本初始版本
 '''
 我理解中国剩余定理:(可能看起来有点绕......仅做参考。你按自己的理解来即可)
 首先拿到一组模数n和一组余数c。
 然后循环,将各数组的除了目前循环数对应的数组外其他的n值拿出来相乘。
 (优化:可先将所有n相乘,再除本组n即可得到这个数)
 然后将上面这个数取余本组n,如果结果不为1,那就乘上一倍,再不行就多乘一倍,以此类推。
 (优化:这里其实就是求个"乘法逆元",乘上一步所得的数即可)
 最后会得到一个符合要求的数,将这个数乘本组c。
 将乘c后的所有这样的值相加,取余所有n相乘,即可得到答案。
 (其实还是要结合“物不知其数”的例子来理解才好)
 '''
 bars = [{"n": 3, "c": 2},
         {"n": 5, "c": 3},
         {"n": 7, "c": 2}
         ]
 superSum = 0    #最终累加值,拿来被(所有n相乘)取余的
 minorCut = 1    #算所有n相乘的值
 chase = 2
 ori = 0
 for run_for_sumBox in range(0, len(bars)):
     sum = 1     #这里我没用数组去存数据,算出一个就加到其他变量里,然后就重置掉
     minorCut *= bars[run_for_sumBox]["n"]   #算所有n相乘的值
     for run_for_sumSingle in range(0, len(bars)):#这循环是当时我用来求“所有n相乘却除本组n”的值的,显然思路不太好,做得太麻烦
         if (run_for_sumBox != run_for_sumSingle):
             sum *= bars[run_for_sumSingle]["n"]
         else:
             continue
     ori = sum       #把上面求出的数备份一下
     while (sum % (bars[run_for_sumBox]["n"]) != 1):#这循环是用来算"乘法逆元"的,即算(所有n相乘却除本组n的值)乘多少再取余本组n能等于1
         sum = ori * chase
         chase += 1
     sum *= bars[run_for_sumBox]["c"]    #使余数从1扩大到原本的c
     superSum += sum         #算最终累加值
 m = superSum % minorCut     #取余一下可以拿到所求值
 print(m)

然而当我拿这个脚本来解决 OldDriver 时,却发现它跑不出答案!

于是我去参考了大佬们的脚本,找到了其中两份,并且对第一份加上了适量注释来辅助理解:

第一份:

 #这个大佬的脚本我修改过了,它原本在我的py3上还跑不出来。于是我对照了另一个大佬的脚本稍稍修改了一下这个脚本,结果它能正常跑出flag。
 import gmpy2
 from Crypto.Util.number import long_to_bytes
 dic =[
     {
         "c": 7366067574741171461722065133242916080495505913663250330082747465383676893970411476550748394841437418105312353971095003424322679616940371123028982189502042,
         "e": 10,
         "n": 25162507052339714421839688873734596177751124036723831003300959761137811490715205742941738406548150240861779301784133652165908227917415483137585388986274803},
     {
         "c": 21962825323300469151795920289886886562790942771546858500842179806566435767103803978885148772139305484319688249368999503784441507383476095946258011317951461,
         "e": 10,
         "n": 23976859589904419798320812097681858652325473791891232710431997202897819580634937070900625213218095330766877190212418023297341732808839488308551126409983193},
     {
         "c": 6569689420274066957835983390583585286570087619048110141187700584193792695235405077811544355169290382357149374107076406086154103351897890793598997687053983,
         "e": 10,
         "n": 18503782836858540043974558035601654610948915505645219820150251062305120148745545906567548650191832090823482852604346478335353784501076761922605361848703623},
     {
         "c": 4508246168044513518452493882713536390636741541551805821790338973797615971271867248584379813114125478195284692695928668946553625483179633266057122967547052,
         "e": 10,
         "n": 23383087478545512218713157932934746110721706819077423418060220083657713428503582801909807142802647367994289775015595100541168367083097506193809451365010723},
     {
         "c": 22966105670291282335588843018244161552764486373117942865966904076191122337435542553276743938817686729554714315494818922753880198945897222422137268427611672,
         "e": 10,
         "n": 31775649089861428671057909076144152870796722528112580479442073365053916012507273433028451755436987054722496057749731758475958301164082755003195632005308493},
     {
         "c": 17963313063405045742968136916219838352135561785389534381262979264585397896844470879023686508540355160998533122970239261072020689217153126649390825646712087,
         "e": 10,
         "n": 22246342022943432820696190444155665289928378653841172632283227888174495402248633061010615572642126584591103750338919213945646074833823905521643025879053949},
     {
         "c": 1652417534709029450380570653973705320986117679597563873022683140800507482560482948310131540948227797045505390333146191586749269249548168247316404074014639,
         "e": 10,
         "n": 25395461142670631268156106136028325744393358436617528677967249347353524924655001151849544022201772500033280822372661344352607434738696051779095736547813043},
     {
         "c": 15585771734488351039456631394040497759568679429510619219766191780807675361741859290490732451112648776648126779759368428205194684721516497026290981786239352,
         "e": 10,
         "n": 32056508892744184901289413287728039891303832311548608141088227876326753674154124775132776928481935378184756756785107540781632570295330486738268173167809047},
     {
         "c": 8965123421637694050044216844523379163347478029124815032832813225050732558524239660648746284884140746788823681886010577342254841014594570067467905682359797,
         "e": 10,
         "n": 52849766269541827474228189428820648574162539595985395992261649809907435742263020551050064268890333392877173572811691599841253150460219986817964461970736553},
     {
         "c": 13560945756543023008529388108446940847137853038437095244573035888531288577370829065666320069397898394848484847030321018915638381833935580958342719988978247,
         "e": 10,
         "n": 30415984800307578932946399987559088968355638354344823359397204419191241802721772499486615661699080998502439901585573950889047918537906687840725005496238621}
 ]
 n = []
 C = []
 for i in dic:   #额外列出组(很明显我自己没有这样做)
     n.append(i["n"])
     C.append(i["c"])
 ​
 N = 1       #算所有n相乘的值
 for i in n:
     N *= i
 ​
 Ni = []     #经过试验发现(我用print把值打出来观察),这里算的是:数组其他n值全提取出来相乘
 for i in n:     #此处直接通过所有n相乘的值除当前组的n来拿到这个数,算是聪明,优化了我的认识
     Ni.append(N // i)   #经过试验发现,这里不用整数除法(//)会出错
 ​
 T = []      #经过试验发现:这是让取余本n等于1所需乘的数,后来发现这个过程叫“乘法逆元”
 for i in range(len(dic)):
     T.append(int(gmpy2.invert(Ni[i], n[i])))     #我才发现gmpy2.invert函数就是专门求这个的......
 ​
 X = 0       ##最终累加值,拿来被(所有n相乘)取余的
 for i in range(len(dic)):
     X += C[i] * Ni[i] * T[i]
 #此处可逆推(我刚开始看代码的时候是从头尾向中间看的),认为Ni[i] * T[i]算的是:数组其他n值全提取出来相乘,反复乘2直到取余本n为1
 ​
 m10 = X % N     #算出m,开10次方,将结果转成字符串
 m = gmpy2.iroot(m10, len(dic))
 #print(libnum.n2s(m[0]))
 print(long_to_bytes(m[0]).decode()) #这个“.decode()”能帮你把“b''”去掉,好技巧!!!

第二份:

 #这原本是前三份中国剩余定理脚本中唯一能跑出flag的一份,厉害!!!
 #我借助这位大佬的脚本来修改其他脚本,使得其他脚本也可跑出flag,感谢这位大佬!!!
 import gmpy2
 from Crypto.Util.number import long_to_bytes
 ​
 def crt(b, m):  #b就是'c',m就是'm'
     # 判断是否互素
     for i in range(len(m) - 1):
         for j in range(i + 1, len(m)):
             # 或者math.gcd()也可以
             if gmpy2.gcd(m[i], m[j]) != 1:
                 print('模数中存在不互质的数!')
                 return -1
 ​
     # 乘积计算
     M = 1
     for i in range(len(m)):
         M *= m[i]
 ​
     Mm = []
     # 求余数 M/m[i]
     for i in range(len(m)):
         Mm.append(M // m[i])
 ​
     # 求Mm[i]的乘法逆元
     T = []
     for i in range(len(m)):
         _, a, _ = gmpy2.gcdext(Mm[i], m[i])
         T.append(int(a % m[i]))
 ​
     # 求的累加
     y = 0
     for i in range(len(m)):
         y += (Mm[i] * T[i] * b[i])
     y = y % M
     return y
 ​
 cip_keys = [
     {
         "c": 7366067574741171461722065133242916080495505913663250330082747465383676893970411476550748394841437418105312353971095003424322679616940371123028982189502042,
         "e": 10,
         "n": 25162507052339714421839688873734596177751124036723831003300959761137811490715205742941738406548150240861779301784133652165908227917415483137585388986274803},
     {
         "c": 21962825323300469151795920289886886562790942771546858500842179806566435767103803978885148772139305484319688249368999503784441507383476095946258011317951461,
         "e": 10,
         "n": 23976859589904419798320812097681858652325473791891232710431997202897819580634937070900625213218095330766877190212418023297341732808839488308551126409983193},
     {
         "c": 6569689420274066957835983390583585286570087619048110141187700584193792695235405077811544355169290382357149374107076406086154103351897890793598997687053983,
         "e": 10,
         "n": 18503782836858540043974558035601654610948915505645219820150251062305120148745545906567548650191832090823482852604346478335353784501076761922605361848703623},
     {
         "c": 4508246168044513518452493882713536390636741541551805821790338973797615971271867248584379813114125478195284692695928668946553625483179633266057122967547052,
         "e": 10,
         "n": 23383087478545512218713157932934746110721706819077423418060220083657713428503582801909807142802647367994289775015595100541168367083097506193809451365010723},
     {
         "c": 22966105670291282335588843018244161552764486373117942865966904076191122337435542553276743938817686729554714315494818922753880198945897222422137268427611672,
         "e": 10,
         "n": 31775649089861428671057909076144152870796722528112580479442073365053916012507273433028451755436987054722496057749731758475958301164082755003195632005308493},
     {
         "c": 17963313063405045742968136916219838352135561785389534381262979264585397896844470879023686508540355160998533122970239261072020689217153126649390825646712087,
         "e": 10,
         "n": 22246342022943432820696190444155665289928378653841172632283227888174495402248633061010615572642126584591103750338919213945646074833823905521643025879053949},
     {
         "c": 1652417534709029450380570653973705320986117679597563873022683140800507482560482948310131540948227797045505390333146191586749269249548168247316404074014639,
         "e": 10,
         "n": 25395461142670631268156106136028325744393358436617528677967249347353524924655001151849544022201772500033280822372661344352607434738696051779095736547813043},
     {
         "c": 15585771734488351039456631394040497759568679429510619219766191780807675361741859290490732451112648776648126779759368428205194684721516497026290981786239352,
         "e": 10,
         "n": 32056508892744184901289413287728039891303832311548608141088227876326753674154124775132776928481935378184756756785107540781632570295330486738268173167809047},
     {
         "c": 8965123421637694050044216844523379163347478029124815032832813225050732558524239660648746284884140746788823681886010577342254841014594570067467905682359797,
         "e": 10,
         "n": 52849766269541827474228189428820648574162539595985395992261649809907435742263020551050064268890333392877173572811691599841253150460219986817964461970736553},
     {
         "c": 13560945756543023008529388108446940847137853038437095244573035888531288577370829065666320069397898394848484847030321018915638381833935580958342719988978247,
         "e": 10,
         "n": 30415984800307578932946399987559088968355638354344823359397204419191241802721772499486615661699080998502439901585573950889047918537906687840725005496238621}
 ]
 ​
 cips = []
 keys = []
 for cip_key in cip_keys:    #一样的,额外列出组
     cips.append(cip_key['c'])
     keys.append(cip_key['n'])
 ​
 r = crt(cips, keys)     #中国剩余定理,拿到明文m
 ​
 res, _ = gmpy2.iroot(r, 10)
 print(res)
 ​
 print(long_to_bytes(res))

最终我站在巨人的肩膀上修改了我最初的代码,得到了最终版代码:

 #中国剩余定理脚本最终版本
 import gmpy2
 from Crypto.Util.number import long_to_bytes
 ​
 bars = [
     {
         "c": 7366067574741171461722065133242916080495505913663250330082747465383676893970411476550748394841437418105312353971095003424322679616940371123028982189502042,
         "e": 10,
         "n": 25162507052339714421839688873734596177751124036723831003300959761137811490715205742941738406548150240861779301784133652165908227917415483137585388986274803},
     {
         "c": 21962825323300469151795920289886886562790942771546858500842179806566435767103803978885148772139305484319688249368999503784441507383476095946258011317951461,
         "e": 10,
         "n": 23976859589904419798320812097681858652325473791891232710431997202897819580634937070900625213218095330766877190212418023297341732808839488308551126409983193},
     {
         "c": 6569689420274066957835983390583585286570087619048110141187700584193792695235405077811544355169290382357149374107076406086154103351897890793598997687053983,
         "e": 10,
         "n": 18503782836858540043974558035601654610948915505645219820150251062305120148745545906567548650191832090823482852604346478335353784501076761922605361848703623},
     {
         "c": 4508246168044513518452493882713536390636741541551805821790338973797615971271867248584379813114125478195284692695928668946553625483179633266057122967547052,
         "e": 10,
         "n": 23383087478545512218713157932934746110721706819077423418060220083657713428503582801909807142802647367994289775015595100541168367083097506193809451365010723},
     {
         "c": 22966105670291282335588843018244161552764486373117942865966904076191122337435542553276743938817686729554714315494818922753880198945897222422137268427611672,
         "e": 10,
         "n": 31775649089861428671057909076144152870796722528112580479442073365053916012507273433028451755436987054722496057749731758475958301164082755003195632005308493},
     {
         "c": 17963313063405045742968136916219838352135561785389534381262979264585397896844470879023686508540355160998533122970239261072020689217153126649390825646712087,
         "e": 10,
         "n": 22246342022943432820696190444155665289928378653841172632283227888174495402248633061010615572642126584591103750338919213945646074833823905521643025879053949},
     {
         "c": 1652417534709029450380570653973705320986117679597563873022683140800507482560482948310131540948227797045505390333146191586749269249548168247316404074014639,
         "e": 10,
         "n": 25395461142670631268156106136028325744393358436617528677967249347353524924655001151849544022201772500033280822372661344352607434738696051779095736547813043},
     {
         "c": 15585771734488351039456631394040497759568679429510619219766191780807675361741859290490732451112648776648126779759368428205194684721516497026290981786239352,
         "e": 10,
         "n": 32056508892744184901289413287728039891303832311548608141088227876326753674154124775132776928481935378184756756785107540781632570295330486738268173167809047},
     {
         "c": 8965123421637694050044216844523379163347478029124815032832813225050732558524239660648746284884140746788823681886010577342254841014594570067467905682359797,
         "e": 10,
         "n": 52849766269541827474228189428820648574162539595985395992261649809907435742263020551050064268890333392877173572811691599841253150460219986817964461970736553},
     {
         "c": 13560945756543023008529388108446940847137853038437095244573035888531288577370829065666320069397898394848484847030321018915638381833935580958342719988978247,
         "e": 10,
         "n": 30415984800307578932946399987559088968355638354344823359397204419191241802721772499486615661699080998502439901585573950889047918537906687840725005496238621}
 ]
 #从这行开始往下,是“中国剩余定理”的本体。其实如果需要,也可以稍加修改写成函数
 superSum = 0    #最终累加值,拿来被(所有n相乘)取余的
 minorSum = 1    #所有n相乘的值
 for run_for_sumBox in range(0, len(bars)):  #算所有n相乘的值
     minorSum *= bars[run_for_sumBox]["n"]
 for run_for_sumBox in range(0, len(bars)):
     sum = minorSum // bars[run_for_sumBox]["n"]     #算所有n相乘却除本组n的值
     sum *= int(gmpy2.invert(sum, bars[run_for_sumBox]["n"]))    #算"乘法逆元",即算(所有n相乘却除本组n的值)乘多少再取余本组n能等于1
     sum *= bars[run_for_sumBox]["c"]        #经上面两步处理过后的值还要再乘本组c,以使余数从1扩大到原本的c
     superSum += sum     #将经本循环处理后得到的数累加起来
 m = superSum % minorSum     #将从第二个循环中产生的数取余所有n相乘的值
 m, _ = gmpy2.iroot(m, len(bars))        #开10次方
 print(long_to_bytes(m).decode())        #以合适的形式打印出来(这里的“.decode()”能去除打印时残余的“b''”)

用自己的脚本得到了flag:


最后补充:

乘法逆元:(此处“乘法逆元”的理解基本限于此题)

在“物不知其数”问题中(详见我前面提到过的“中国剩余定理”原理文章),当我们将3、5、7中的5、7拎出来相乘时,能得到35。(在脚本中是3、5、7相乘再除3,殊途同归)

这时候,如果让35去取余3,不会得到1,而是2。但是中国剩余定理认为我们应该让这个结果为1,所以我们把35乘一倍(也就是乘2),而这回再去取余就能得到1了:

                                                35*2~(mod~3)=1

从这个角度来看,乘法逆元就是求出这个“2”,求出在这个位置上的值是多少。

对应到Python代码中,如果你有这样一个数学关系:

                                                a*b~(mod~c)=1

那么你可以写这段Python代码来求b:(记得 import gmpy2 库!)

b = int(gmpy2.invert(a, c))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值