RSA-p和q挨得很近
作者:互联网
一、基础
最简单的就是拿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的"中间值"(),然后让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,但是他没有将原理,一笔带过了。
题目:
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的中间值()很近。这并不是真正意义上的中间值,只是说相对于别的解,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 = 0x10001flag = xxx
m = bytes_to_long(flag)
c = pow(m,e,n)
print(c)
print(n)'''
5883797662470459824355663245986072888499217007658131616834157815812099907584034205088255553387720712715657503553785084616903197734118992506040765948815581238738585159640841277023597023582148173041980600751980206228524475872232080917683822098342300418744639304147771013376863895727877847094151770079046205501266017838881847833528612089868825489776289686550273385136080255799772961155599801690997753649087689949021276549323525754963020408864310302166537661098308581259246052869844362142747080042122189010627048397501817473817946566885487595098504403459522534124404289032779842658407728856164570059823567667669076044563549721918886430160041337156249733571322684187916005175717585587552966989348534775572282369273898182367851689305440672199427492706130124832744127722533758962606513875787129378871099575729793745175327897215145024490319291830298017471555440811147903390803597635585696411407922981136489077349754222355529320548946411677051716584081079246752768224289803323109047467790868885987703125118276891234633889937243303027095375365791207055516900563280115276282761652663098154769929217653527103304045922204641545963828632051715956492613217136463227530538723452005224696385225174844198627387638874395654771260577791169209134146482
371836308886540426192412096148744468186415625392487977879857531835902736615143801798286888910032757343063307437491756141584074211336204232321625860256198232674594289958977877151673559656231508894335267778421247120253811435320830719345924114507429603444867321985950626826991173077205178053362583897682032724665933945097478196733856621304091584618890629791164070168813615231192565754075364366134730406435348259862415601279551372742556900223695625597120400693500365067997937729674171334150610370961480163812842105971064886537235753552837000236613769498285320938741476925731411679897178247509473618923405834484514661807520252213326586104301410231354079662448182315435504639054167776200376152713328322609890314052157497227912497420886067642369853988427179097601651852373889536473835216949882465614231082448644133599830105850384251912580667211045553849789111685933572279734855596537588506333965238289830492091608095939699649204953662409772326162756616403885752077614154740093699490363803868230526757718971893753734479487055548790771458190489276504470984092766005111535651632518882006617378156289619913024674060627173821938856436490090896481522906788847664717355154445108253949612361422754030509689952049972855384980134472281224218581516679
'''
分析:
可以看出: p和q很近,但不是完全挨着的,所以第一种方法就失效了,我们只能用第二种方法了。令a是n的中间值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的文章:
标签:prime,q1,p1,gmpy2,iroot,RSA,挨得,print 来源: https://blog.csdn.net/hacker_zrq/article/details/121444869