ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

RSA-p和q挨得很近

2021-11-20 22:33:50  阅读:234  来源: 互联网

标签:prime q1 p1 gmpy2 iroot RSA 挨得 print


一、基础

最简单的就是拿yafu直接分解,但是我们得知道那个算法的原理,

        就是现在p,q是两个素数,而且他俩在素数序列里面就是一前一后的关系。所以我们要把他俩的乘积开根号得到的结果一定是在p,q之间的一个数字,(而且一定不是素数,因为p,q就是紧邻的两个素数)。

           那我们找这个开方出来的数字的下一个素数,一定是q,因此我们再让n/q就可以得到两个素数。(这是第一种方法,必须得保证两个数为素数,而且挨得很近才行,我们还会介绍第二种方法,即使有一个不是素数也可以解决。)

'''生成两个挨得近的素数p,q'''
p = getPrime(512)
q = gmpy2.next_prime(p)
n=p*q
print(p)
print(q)
print(n)

'''开始破解'''
temp=gmpy2.iroot(n,2)[0]  #下面会介绍这个函数的用法
p=gmpy2.next_prime(temp)
q=n//p
print(p)
print(q)

 插入:介绍gmpy2的iroot函数,这个函数专门用来进行大数开根号,gmpy2.iroot(n,t)。n就是大整数,t是你要开几次幂。

n = 25090599929998210805842179282010892518788774707524638919079437546041232793900321811241137174436965015616090258924169447468139697688937237025509597680391508555749204353178672698784759792195141661434163809407121898399491900074041853967956481880690069324590880495900272708614479483939242962853655449365679871506290712104139043498133484229702911989500930216839263081488062817080043580519435821704452166687962258543290861642124944113387024276748328363981567361186204753673408517208885593967345448724464638916881282723847845005156574391814533553317383170531212134424920411849924841268526337807027963471928363537964205561663
print(gmpy2.iroot(n,3))

注意结果的形式:前面开根号的结果,后面的true或false表示是否是整开的。比如你要对8开3次幂,后面就是true。

 二、第二中方法。平方差遍历法。

核心总结就是:令a是n的"中间值"(\sqrt{n}),然后让a以步长为1自增遍历,直到pow(a,2)-n的结果可以正好开方为止。那个结果开方就是b。

 整个例子看看。

'''生成两个挨得近的素数p,q'''
p = getPrime(512)
q = gmpy2.next_prime(p)
n=p*q
print(p)
print(q)
print(n)



print('开始破解')
'''开始破解'''
a=gmpy2.iroot(n,2)[0]
while 1:   #破解出来一组就行了,一般也就一组,挨得很近的话很快就出来了,如果长时间还没出来就可以换方法了,不要指望着他遍历所有的,到死也弄不完。
    B2=pow(a,2)-n
    a+=1
    if gmpy2.is_square(B2):
        b=gmpy2.iroot(B2,2)[0]
        p=a+b
        q=a-b
        print(p)
        print(q)
        break

三、dl在文章里给出了一道绿城杯的原题,我在后面附加了一道moectf的原题。

①、绿城杯

完整的EXP可以看这位dl的 WP,但是他没有将原理,一笔带过了。

(8条消息) 2021年“绿城杯”网络安全大赛-Crypto-RSA2-PLUS_夜白君的博客-CSDN博客

题目:

from Crypto.Util.number import *
import gmpy2
from flag import flag
assert flag[:5]==b'flag{'
​
m1 = bytes_to_long(flag[:20])
p  = getPrime(512)
p1 = gmpy2.next_prime(p)
q  = getPrime(512)
q1 = gmpy2.next_prime(q)


n1 = p*q*p1*q1
print('n1 =',n1)
e = 0x10001
c1 = pow(m1,e,n1)
print('c1 =',c1)
​
#n1 = 6348779979606280884589422188738902470575876294643492831465947360363568026280963989291591157710389629216109615274754718329987990551836115660879103234129921943824061416396264358110216047994331119920503431491509529604742468032906950984256964560405062345280120526771439940278606226153077959057882262745273394986607004406770035459301695806378598890589432538916219821477777021460189140081521779103226953544426441823244765828342973086422949017937701261348963541035128661464068769033772390320426795044617751909787914185985911277628404632533530390761257251552073493697518547350246993679844132297414094727147161169548160586911
#c1 = 6201882078995455673376327652982610102807874783073703018551044780440620679217833227711395689114659144506630609087600915116940111002026241056808189658969089532597757995423694966667948250438579639890580690392400661711864264184444018345499567505424672090632235109624193289954785503512742400960515331371813467034511130432319427185134018830006918682733848618201088649690422818940385123599468595766345668931882249779415788129316594083269412221804774856038796248038700275509397599351533280014908894068141056694660319816046357462684688942519849441237878018480036145051967731081582598773076490918572392784684372694103015244826

 分析:

p  = getPrime(512)
p1 = gmpy2.next_prime(p)
q  = getPrime(512)
q1 = gmpy2.next_prime(q)

可以看出,p和p1紧紧挨着,q和q1紧紧挨着。所以要是把n因式分解的话可能得到7种结果。

由于p和p1挨得近,q和q1挨得近。所以我们知道,下面这两组解离n的中间值(\sqrt{n})很近。这并不是真正意义上的中间值,只是说相对于别的解,pq和p1*q1(p*q1和q*p1)挨着相对很近。这就了我们利用上面漏洞的机会。

所以那么我们如果使用上面的第二个脚本那种方法(费马分解),我们就可以在短时间内爆破出这两组非质数的解(但是别的组由于隔得远,所以得花很长时间,不过别的那几组解对我们来说也没什么用),而且因为我们知道它其实是从‘中间’开始往两边爆破的,一旦我们两组解都有了,求它们的公因数就能得到q或p的值,从而得到所有4个因子的值。

exp如下: 

n1 = 6348779979606280884589422188738902470575876294643492831465947360363568026280963989291591157710389629216109615274754718329987990551836115660879103234129921943824061416396264358110216047994331119920503431491509529604742468032906950984256964560405062345280120526771439940278606226153077959057882262745273394986607004406770035459301695806378598890589432538916219821477777021460189140081521779103226953544426441823244765828342973086422949017937701261348963541035128661464068769033772390320426795044617751909787914185985911277628404632533530390761257251552073493697518547350246993679844132297414094727147161169548160586911
c1 = 6201882078995455673376327652982610102807874783073703018551044780440620679217833227711395689114659144506630609087600915116940111002026241056808189658969089532597757995423694966667948250438579639890580690392400661711864264184444018345499567505424672090632235109624193289954785503512742400960515331371813467034511130432319427185134018830006918682733848618201088649690422818940385123599468595766345668931882249779415788129316594083269412221804774856038796248038700275509397599351533280014908894068141056694660319816046357462684688942519849441237878018480036145051967731081582598773076490918572392784684372694103015244826

def factor(n):
    list = []
    a = gmpy2.iroot(n, 2)[0]
    while 1:
        B2 = pow(a, 2) - n
        if gmpy2.is_square(B2):
            b = gmpy2.iroot(B2, 2)[0]
            pq = a - b
            p1q1 = a + b
            list.append([pq, p1q1])
            print(pq)
            print(p1q1)
            if len(list) == 2:
                break
        a += 1  # 注意这个a的位置,别放错了,你要放到前面就错了,不信试试
    return list


list = factor(n1)

'''两组解'''
X1, Y1 = list[0]
X2, Y2 = list[1]
'''求公约数'''
p = gmpy2.gcd(X1, X2)
q = gmpy2.gcd(Y1, Y2)
'''求另一个数字'''
p1 = X2 // p
q1 = Y2 // q

'''RSA解密'''
f = (p - 1) * (q - 1) * (p1 - 1) * (q1 - 1)
print(long_to_bytes(pow(c1, gmpy2.invert(e, f), n1)))
#关于最后一步也算是RSA的一个小变种,往常都是两个大素数,现在一下子变成四个了,不管几个,都按照原来的模子。

②、moectf 

题目:

import gmpy2
from Crypto.Util.number import * 
p = getPrime(2048) 
q = gmpy2.next_prime(p)
for i in range(3600):
    if i%100 ==0:
        print(i)
    q = gmpy2.next_prime(q)

n = p * q
e = 0x10001

flag = xxx
m = bytes_to_long(flag)
c = pow(m,e,n)
print(c)
print(n)

'''
5883797662470459824355663245986072888499217007658131616834157815812099907584034205088255553387720712715657503553785084616903197734118992506040765948815581238738585159640841277023597023582148173041980600751980206228524475872232080917683822098342300418744639304147771013376863895727877847094151770079046205501266017838881847833528612089868825489776289686550273385136080255799772961155599801690997753649087689949021276549323525754963020408864310302166537661098308581259246052869844362142747080042122189010627048397501817473817946566885487595098504403459522534124404289032779842658407728856164570059823567667669076044563549721918886430160041337156249733571322684187916005175717585587552966989348534775572282369273898182367851689305440672199427492706130124832744127722533758962606513875787129378871099575729793745175327897215145024490319291830298017471555440811147903390803597635585696411407922981136489077349754222355529320548946411677051716584081079246752768224289803323109047467790868885987703125118276891234633889937243303027095375365791207055516900563280115276282761652663098154769929217653527103304045922204641545963828632051715956492613217136463227530538723452005224696385225174844198627387638874395654771260577791169209134146482
371836308886540426192412096148744468186415625392487977879857531835902736615143801798286888910032757343063307437491756141584074211336204232321625860256198232674594289958977877151673559656231508894335267778421247120253811435320830719345924114507429603444867321985950626826991173077205178053362583897682032724665933945097478196733856621304091584618890629791164070168813615231192565754075364366134730406435348259862415601279551372742556900223695625597120400693500365067997937729674171334150610370961480163812842105971064886537235753552837000236613769498285320938741476925731411679897178247509473618923405834484514661807520252213326586104301410231354079662448182315435504639054167776200376152713328322609890314052157497227912497420886067642369853988427179097601651852373889536473835216949882465614231082448644133599830105850384251912580667211045553849789111685933572279734855596537588506333965238289830492091608095939699649204953662409772326162756616403885752077614154740093699490363803868230526757718971893753734479487055548790771458190489276504470984092766005111535651632518882006617378156289619913024674060627173821938856436490090896481522906788847664717355154445108253949612361422754030509689952049972855384980134472281224218581516679
'''

分析:

可以看出: p和q很近,但不是完全挨着的,所以第一种方法就失效了,我们只能用第二种方法了。令a是n的中间值n的中间值(\sqrt{n})然后去遍历,看什么时候可以得到一个正正好好的平方数。 

c = 5883797662470459824355663245986072888499217007658131616834157815812099907584034205088255553387720712715657503553785084616903197734118992506040765948815581238738585159640841277023597023582148173041980600751980206228524475872232080917683822098342300418744639304147771013376863895727877847094151770079046205501266017838881847833528612089868825489776289686550273385136080255799772961155599801690997753649087689949021276549323525754963020408864310302166537661098308581259246052869844362142747080042122189010627048397501817473817946566885487595098504403459522534124404289032779842658407728856164570059823567667669076044563549721918886430160041337156249733571322684187916005175717585587552966989348534775572282369273898182367851689305440672199427492706130124832744127722533758962606513875787129378871099575729793745175327897215145024490319291830298017471555440811147903390803597635585696411407922981136489077349754222355529320548946411677051716584081079246752768224289803323109047467790868885987703125118276891234633889937243303027095375365791207055516900563280115276282761652663098154769929217653527103304045922204641545963828632051715956492613217136463227530538723452005224696385225174844198627387638874395654771260577791169209134146482
n = 371836308886540426192412096148744468186415625392487977879857531835902736615143801798286888910032757343063307437491756141584074211336204232321625860256198232674594289958977877151673559656231508894335267778421247120253811435320830719345924114507429603444867321985950626826991173077205178053362583897682032724665933945097478196733856621304091584618890629791164070168813615231192565754075364366134730406435348259862415601279551372742556900223695625597120400693500365067997937729674171334150610370961480163812842105971064886537235753552837000236613769498285320938741476925731411679897178247509473618923405834484514661807520252213326586104301410231354079662448182315435504639054167776200376152713328322609890314052157497227912497420886067642369853988427179097601651852373889536473835216949882465614231082448644133599830105850384251912580667211045553849789111685933572279734855596537588506333965238289830492091608095939699649204953662409772326162756616403885752077614154740093699490363803868230526757718971893753734479487055548790771458190489276504470984092766005111535651632518882006617378156289619913024674060627173821938856436490090896481522906788847664717355154445108253949612361422754030509689952049972855384980134472281224218581516679
e = 0x10001


def factor(n):
    a = gmpy2.iroot(n, 2)[0]
    while 1:
        B2 = pow(a, 2) - n
        if gmpy2.is_square(B2):
            b = gmpy2.iroot(B2, 2)[0]
            p = a + b
            q = a - b
            return p, q
        a += 1  # 千万别忘了a的自增步长为1

p,q=factor(n)
f = (p - 1) * (q - 1)
d = gmpy2.invert(e, f)
print(long_to_bytes(pow(c, d, n)))

参考这个dl的文章:

浅析RSA因子大小相近时分解因子攻击方法 - FreeBuf网络安全行业门户 

 

标签:prime,q1,p1,gmpy2,iroot,RSA,挨得,print
来源: https://blog.csdn.net/hacker_zrq/article/details/121444869

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有