每日10行代码170:rsa中的N分解问题,基于p和q之间的关系

前几天搞ctf,遇到一道常规的rsa题目 :

import sympy
from Crypto.Util.number import *

flag = b"DASCTF{xxxxx}"

x=getPrime(1024)
p=sympy.nextprime(11*x)
q=sympy.prevprime(23*x)
n=p*q

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

print("n=",n)
print("c=",c)

#n= 7099293997597057840121358666833837753498838275854020154482887743106000287292796543920866875062689995360025217485874831332257233130287943206444475190268445255670322843664471682348256156185175655765790452094332875022809494407318056044647005041845654843080303742522260061500210481600297956451426162674923926908156645992521694195572818623774054219194331159529364179241757932761459930262573830738911713799216140111007655256112125121081747854267340976432923900792983659847629430766080521995039114172477341269935779097804051557556063477903826454634581880779164839924381664510909546228996769947966559112620828323435423467787739
#c= 3078278882403267771557339568388950410639470501469121937324913253244013904986826470346335611174822666010160930623609201021876295254455820936788078951586549877513565571795083091146694885452347963070384765951180432581796819616400782006993357703440486783144989291310259039645268226860339316323226395210408787702054635889745582356633806087632054473023928020827581196829103923740718937874920893533975613493768492615364149440810394033176498488161704634307874672531940341631965894022899665283833912182388412943227149695408964841000543086601596551360786212024360389301448828142199899595307482885969343432562999657817232668321784

这道题的钥匙关键是

x=getPrime(1024)
p=sympy.nextprime(11*x)
q=sympy.prevprime(23*x)
n=p*q

从这里可以发现p和q有一定的关系

p=11x+t
q=23x-m

其中t和m是一个很小的量,t代表11x到下一个素数之间的差值,经过测试,通常差值在5000以内。
由于t和m很小,那么相当于
p = 11 × x p=11\times x p=11×x
q = 23 × x q=23\times x q=23×x

q = 11 23 × p q=\frac{11}{23}\times p q=2311×p
n = p × q = p × 11 23 × p = 11 23 p 2 n=p \times q=p \times \frac{11}{23}\times p= \frac{11}{23} p^2 n=p×q=p×2311×p=2311p2
p = 23 11 × n p=\sqrt{\frac{23}{11}\times n} p=1123×n

有这个关系那么就证明,p在 23 11 × n \sqrt{\frac{23}{11}\times n} 1123×n 左右浮动,于是可以写出以下代码:

import sympy
from Crypto.Util.number import *
import gmpy2
n= 7099293997597057840121358666833837753498838275854020154482887743106000287292796543920866875062689995360025217485874831332257233130287943206444475190268445255670322843664471682348256156185175655765790452094332875022809494407318056044647005041845654843080303742522260061500210481600297956451426162674923926908156645992521694195572818623774054219194331159529364179241757932761459930262573830738911713799216140111007655256112125121081747854267340976432923900792983659847629430766080521995039114172477341269935779097804051557556063477903826454634581880779164839924381664510909546228996769947966559112620828323435423467787739

pp = n*11//23
p= gmpy2.iroot(pp,2)
floating_rng=1000
for i in range(p[0]-floating_rng, p[0]+floating_rng):
    q = divmod(n,i)
    if q[1]==0:
        print("p等于:",i,"\nq等于:",q[0])

事实证明,真实的p值在平方根上下1000之内浮动,类似的,可以解决其他类似这种知道p和q某种关系的rsa问题。

求出p,q后,解题过程 :

import libnum
import gmpy2
from Crypto.Util.number import * 

p=1842637924441450658998064063974279963201497691391749603710761739729251804071657434195607292881514041836386466090902459885504202102210726839134119973707983797822067691969510912653597933390722892316816352503877596316419304279111171622418905923075098131685080061845058416898784321859891210483357866757221330352431 
q=3852788387468487741541406679218949013966767900182749171395229092161162863058920089681724339661347542021535338190068779760599695304622428845462250854116693395446141537754431908275704769816966047571525100689925883207058545310868813392330439657338841548068803765676031235333821763888863440101566448674190054370069
c=3078278882403267771557339568388950410639470501469121937324913253244013904986826470346335611174822666010160930623609201021876295254455820936788078951586549877513565571795083091146694885452347963070384765951180432581796819616400782006993357703440486783144989291310259039645268226860339316323226395210408787702054635889745582356633806087632054473023928020827581196829103923740718937874920893533975613493768492615364149440810394033176498488161704634307874672531940341631965894022899665283833912182388412943227149695408964841000543086601596551360786212024360389301448828142199899595307482885969343432562999657817232668321784

#phi=(p-1)*(q-1)
e=0xe18e
#d = libnum.invmod(e,phi) 

# 当e约去公约数后与phi互素
def decrypt(p, q, e, c):
    n = p * q
    phi = (p - 1) * (q - 1)
    t = gmpy2.gcd(e, phi)
    d = gmpy2.invert(e // t, phi)
    m = pow(c, d, n)
    print(m)
    msg = gmpy2.iroot(m, t)
    print(msg)
    if msg[1]:
        print(long_to_bytes(msg[0]))

decrypt(p,q,e,c)

输出结果:

788405031745507770194690962903400949406743404033876736594470380622736446808280639069799390802178272301446577152339579723271862025
(mpz(28078551097688565920863135908056268375491504812717619527898702205), True)
b'DASCTF{RSA_1s_Re@lly_e4sy!}'

这道题 还藏了一个小陷阱,就是题目中的e和phi不互素,所以不能直接求逆元,所以需要去除公约数(假如为g)后求逆元,但是这样做了后,最后结果需要开g次方才能得到 真实的结果 (至于为什么是开g次方,需要数学推导)。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值