buuctf的RSA(五)

news2025/1/20 5:49:36

[RoarCTF2019]RSA

     一看到题目,我就有些蒙了,A是代表了什么,

先来分解n

接下来可以暴力破解e了,因为e没有给出来,应该不会太大,猜测是四位数字


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

A = 2683349182678714524247469512793476009861014781004924905484127480308161377768192868061561886577048646432382128960881487463427414176114486885830693959404989743229103516924432512724195654425703453612710310587164417035878308390676612592848750287387318129424195208623440294647817367740878211949147526287091298307480502897462279102572556822231669438279317474828479089719046386411971105448723910594710418093977044179949800373224354729179833393219827789389078869290217569511230868967647963089430594258815146362187250855166897553056073744582946148472068334167445499314471518357535261186318756327890016183228412253724
n = 117930806043507374325982291823027285148807239117987369609583515353889814856088099671454394340816761242974462268435911765045576377767711593100416932019831889059333166946263184861287975722954992219766493089630810876984781113645362450398009234556085330943125568377741065242183073882558834603430862598066786475299918395341014877416901185392905676043795425126968745185649565106322336954427505104906770493155723995382318346714944184577894150229037758434597242564815299174950147754426950251419204917376517360505024549691723683358170823416757973059354784142601436519500811159036795034676360028928301979780528294114933347127
c = 41971850275428383625653350824107291609587853887037624239544762751558838294718672159979929266922528917912189124713273673948051464226519605803745171340724343705832198554680196798623263806617998072496026019940476324971696928551159371970207365741517064295956376809297272541800647747885170905737868568000101029143923792003486793278197051326716680212726111099439262589341050943913401067673851885114314709706016622157285023272496793595281054074260451116213815934843317894898883215362289599366101018081513215120728297131352439066930452281829446586562062242527329672575620261776042653626411730955819001674118193293313612128

print(len(str(A)))

q = 842868045681390934539739959201847552284980179958879667933078453950968566151662147267006293571765463137270594151138695778986165111380428806545593588078365331313084230014618714412959584843421586674162688321942889369912392031882620994944241987153078156389470370195514285850736541078623854327959382156753458569
p = 139916095583110895133596833227506693679306709873174024876891023355860781981175916446323044732913066880786918629089023499311703408489151181886568535621008644997971982182426706592551291084007983387911006261442519635405457077292515085160744169867410973960652081452455371451222265819051559818441257438021073941183

phi = (p - 1) * (q - 1)
# ed=k*phi+1
for e in range(100000):
    if gmpy2.gcd(e, phi) == 1:
        d = gmpy2.invert(e, phi)
        m = gmpy2.powmod(c, d, n)
        m = libnum.n2s(int(m))      #libnum.n2s 函数用于将整数转换为字节串
        if 'CTF' in str(m):
            print(m)
            break


 

根据以上,似乎没有发挥A的作用,没有直接参与RSA的解密过程

看了其他大神的wp,似乎常规解法是根据A来推测x,y的范围,解出x,y,根据q与iroot(n/(x*y),2)的值相接近.从而可以得出p,q的值.

import gmpy2

count = 0
min_gap = 99999
max_gap = 0
p = 21679967315669523832823488086602270908640556452221643267343405142715107120582778258062778680925402382895255206278432676733248308929062714997512704088603667
for i in range(1000):
    pn = gmpy2.next_prime(p)
    count = count + pn - p
    max_gap = max(max_gap, pn - p)
    min_gap = min(min_gap, pn - p)
    p = pn

print(count / 1000)
print(min_gap)
print(max_gap)

这是

155位(10进制)左右素数之间gap的大小,然后确定爆破的范围,

分析x,y的关系

      A转化为2进制后是2017位,而说明第一项只能为1,相比于第二项,第三项可以忽略,所以对A开316次根,得到y的估计值为83,考虑忽略项,实际y的值小于等于83

明显可以知道,x=2,y=83

import math
A = 2683349182678714524247469512793476009861014781004924905484127480308161377768192868061561886577048646432382128960881487463427414176114486885830693959404989743229103516924432512724195654425703453612710310587164417035878308390676612592848750287387318129424195208623440294647817367740878211949147526287091298307480502897462279102572556822231669438279317474828479089719046386411971105448723910594710418093977044179949800373224354729179833393219827789389078869290217569511230868967647963089430594258815146362187250855166897553056073744582946148472068334167445499314471518357535261186318756327890016183228412253724
for y in range(2, 85):
    for x in range(2, 100):
        try:
            a=(((y%x)**5)%(x%y))**2019+y**316+(y+1)//x
            if a-A <= 1000 and a- A>= -1000:
                print(x, y, a-A)
        except:
            pass

暴力破解了x,y,

后面就可以根据x,y推出p,q了

import gmpy2

n = 117930806043507374325982291823027285148807239117987369609583515353889814856088099671454394340816761242974462268435911765045576377767711593100416932019831889059333166946263184861287975722954992219766493089630810876984781113645362450398009234556085330943125568377741065242183073882558834603430862598066786475299918395341014877416901185392905676043795425126968745185649565106322336954427505104906770493155723995382318346714944184577894150229037758434597242564815299174950147754426950251419204917376517360505024549691723683358170823416757973059354784142601436519500811159036795034676360028928301979780528294114933347127


def trybomb(t):
    print('when t is ' + str(t) + ' :')
    pv = gmpy2.isqrt(n // t) - 2000
    count = 1
    while count <= 1000:
        p = gmpy2.next_prime(pv)
        count += 1
        if n % p == 0:
            print('p = ', p)
            q = n // p
            break
        else:
            pv = p


trybomb(166)
print('finish')

最后还是暴力破解出来e

[RoarCTF2019]babyRSA

题目看起来很复杂,但是你去将n分解一下,发现了刚好可以分解成三个素数,就变得很简单了

直接得到了flag

import libnum
c=75700883021669577739329316795450706204502635802310731477156998834710820770245219468703245302009998932067080383977560299708060476222089630209972629755965140317526034680452483360917378812244365884527186056341888615564335560765053550155758362271622330017433403027261127561225585912484777829588501213961110690451987625502701331485141639684356427316905122995759825241133872734362716041819819948645662803292418802204430874521342108413623635150475963121220095236776428
e=4097  #将0x1001转化为十进制数
r=1276519424397216455160791032620569392845781005616561979809403385593761615670426423039762716291920053306063214548359656555809123127361539475238435285654851
p=5057572094237208127867754008134739503717927865750318894982404287656747895573075881186030840558129423864679886646066477437020450654848839861455661385205433
q=13242175493583584108411324143773780862426183382017753129633978933213674770487765387985282956574197274056162861584407275172775868763712231230219112670015751
n=p*q*r
phi =(p-1)*(q-1)*(r-1)
d=libnum.invmod(e,phi)
m=pow(c,d,n)
print(libnum.n2s(m))

    维纳攻击:

            e的指数很大(理论上d<N**0.25作为攻击的实现)

实现Wiener攻击,这是一种针对具有较小解密指数d的RSA私钥的恢复

维纳攻击你要先知道以下几个知识点

        连分数:

      连分数的定义

连分数是一种特殊的分数表示法,其形式如下:

  

      其中,a0​是某个整数,而所有其他的数an​(n>0)都是正整数。连分数可以是有限的(即终止于某个an​),也可以是无限的(即不终止)。在数学中,任何一个有理数都可以表示为有限连分数,而任何一个无理数都可以表示为无限连分数。

      连分数在RSA中的应用

  1. 理论基础:连分数在RSA中的应用通常与Wiener攻击有关。Wiener攻击是一种利用RSA私钥的某些性质(如解密指数d较小)来恢复私钥的攻击方法。在这种攻击中,连分数被用来求解与私钥相关的同余方程。
  2. Wiener攻击:Wiener攻击基于一个数学定理,该定理允许我们根据给定的实数a和某个条件来求解整数p和q。在RSA的上下文中,这个实数a可能与私钥的某些属性相关,而p和q则是模数N的质因子。通过求解与a相关的连分数,攻击者可以逐步逼近p和q的值,并最终恢复私钥。
  3. 实际运用:在实际运用中,Wiener攻击需要满足一定的条件才能成功。例如,解密指数d必须小于某个阈值(这个阈值通常与模数N的大小有关)。此外,攻击者还需要能够获取到足够多的关于私钥的信息(如公钥e和模数N)。如果这些条件都得到满足,那么攻击者就可以使用连分数技术来恢复私钥。

        韦达定理

  韦达定理在二次方程 ax^2 + bx + c = 0

      根的和等于系数 b 的相反数除以系数 a,即 x_1 + x_2 = -b/a

       根的积等于常数项 c 除以系数 a,即 x_1 * x_2 = c/a

         来自己出一道题目

import libnum
import random
#生成随机的素数
p=libnum.generate_prime(512)
q=libnum.generate_prime(512)
m="flag{h3ll0-w0rld}"
#字符串转数字
m=libnum.s2n(m)
n=p*q
phi_n=(p-1)*(q-1)
#计算d
while True:
    nbits=1024
    d=random.getrandbits(nbits //4)
    if (libnum.gcd(d,phi_n)  ==1 and 36*pow(d,4) <n):
        break

#计算出e
e=libnum.invmod(d,phi_n)
c=pow(m,e,n)
print("n=",n)
print("e=",e)
print("c=",c)

完整代码:

import gmpy2
import libnum

def continuedFra(x, y):
   # #此函数用于计算x/y的连分数表示。它使用辗转相除法(欧几里得算法)来逐步减少分数,直到分母y变为0。
  
    cf = []
    while y:
        cf.append(x // y)
        x, y = y, x % y
    return cf
def gradualFra(cf):
  # #这个函数接收一个连分数列表cf,并返回列表最后一个元素的渐近分数。它通过逆序遍历连分数列表,并使用特定的公式来计算分子和分母
    numerator = 0
    denominator = 1
    for x in cf[::-1]:
        # 这里的渐进分数分子分母要分开
        numerator, denominator = denominator, x * denominator + numerator
    return numerator, denominator
def solve_pq(a, b, c):
    """使用韦达定理解出pq,x^2−(p+q)∗x+pq=0
    :param a:x^2的系数
    :param b:x的系数
    :param c:pq
    :return:p,q
    """
    par = gmpy2.isqrt(b * b - 4 * a * c)
    return (-b + par) // (2 * a), (-b - par) // (2 * a)
def getGradualFra(cf):
    """计算列表所有的渐近分数
    :param cf: 连分数列表
    :return: 该列表所有的渐近分数
    """
    gf = []
    for i in range(1, len(cf) + 1):
        gf.append(gradualFra(cf[:i]))
    return gf


def wienerAttack(e, n):
   #它首先计算公钥e相对于模数n的连分数表示,然后使用getGradualFra函数生成所有可能的渐近分数。对于每个渐近分数(d, k),它检查是否满足(e * d - 1) % k == 0。如果满足,它尝试使用(e * d - 1) // k作为phi(n)的近似值,并使用solve_pq函数尝试分解n以找到p和q。如果找到了有效的p和q,那么它会计算私钥d并返回
    cf = continuedFra(e, n)
    gf = getGradualFra(cf)
    for d, k in gf:
        if k == 0: continue
        if (e * d - 1) % k != 0:
            continue
        phi = (e * d - 1) // k
        p, q = solve_pq(1, n - phi + 1, n)
        if p * q == n:
            return d
n= 92524912824457455478469479834145192399327339422419976426014024967106017250525784362251809870851330233714073309745926853809722723590007799727853843200857232710763391103522003213039635901415434225633578811817814757637106456030410677721613532510535968977938933636723316561537077411888416685226759599589065857021
e= 54061685907559431614093395962586317025387379705558008571034720802508811703397874391457074838986258081858042924777974376782261530254408986545475988227306300250798769475295193119450403415247506835654081051816773486037227848499432844796357648121686484398862179371192675792796946629089692057399103015987899220553
c= 75914541873509926793052668657170821143574989686045126269695603145212114658529526002484357527707015025922193311737442791537506782543615634954764108902795246498210682486601649383685688201749284019581721635618585026491003845052815757860692633274121793700743169931534720441816541558209434925881957085594022520969


d=wienerAttack(e, n)
m=pow(c, d, n)
print(libnum.n2s(m).decode())

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

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

相关文章

2024就业寒潮下的挑战与机遇:能否守住饭碗,人工智能能否成为新春天?

前言 随着时代的飞速发展&#xff0c;2024年的就业市场迎来了前所未有的挑战。数以百万计的高校毕业生涌入市场&#xff0c;使得就业竞争愈发激烈。然而&#xff0c;在这股就业寒潮中&#xff0c;我们也看到了新的曙光——人工智能的崛起。这一新兴行业以其独特的魅力和巨大的…

【每日刷题】Day52

【每日刷题】Day52 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 2965. 找出缺失和重复的数字 - 力扣&#xff08;LeetCode&#xff09; 2. 350. 两个数组的交集 II …

【LeetCode】38.外观数列

外观数列 题目描述&#xff1a; 「外观数列」是一个数位字符串序列&#xff0c;由递归公式定义&#xff1a; countAndSay(1) "1"countAndSay(n) 是 countAndSay(n-1) 的行程长度编码。 行程长度编码&#xff08;RLE&#xff09;是一种字符串压缩方法&#xff0c…

【评价类模型】熵权法

1.客观赋权法&#xff1a; 熵权法是一种客观求权重的方法&#xff0c;所有客观求权重的模型中都要有以下几步&#xff1a; 1.正向化处理&#xff1a; 极小型指标&#xff1a;取值越小越好的指标&#xff0c;例如错误率、缺陷率等。 中间项指标&#xff1a;取值在某个范围内较…

【QEMU中文文档】1.关于QEMU

本文由 AI 翻译&#xff08;ChatGPT-4&#xff09;完成&#xff0c;并由作者进行人工校对。如有任何问题或建议&#xff0c;欢迎联系我。联系方式&#xff1a;jelin-shoutlook.com。 QEMU 是一款通用的开源机器仿真器和虚拟化器。 QEMU 可以通过几种不同的方式使用。最常见的用…

Linux上传文件

在finalshell中连接的Linux系统中&#xff0c;输入命令rz然后选择windows中的文件即可。

多维数组操作,不要再用遍历循环foreach了!来试试数组展平的小妙招!array.flat()用法与array.flatMap() 用法及二者差异详解

目录 一、array.flat&#xff08;&#xff09;方法 1.1、array.flat&#xff08;&#xff09;的语法及使用 ①语法 ②返回值 ③用途 二、array.flatMap() 方法 2.1、array.flatMap()的语法及作用 ①语法 ②返回值 ③用途 三、array.flat&#xff08;&#xff09;与a…

Nature 审稿人:值得关注的里程碑!段路明研究组首次实现基于数百离子量子比特的量子模拟计算

2024年5月30日&#xff0c;清华大学最新科研成果发表于Nature&#xff08;自然&#xff09;&#xff0c;这项成果被Nature审稿人称为“量子模拟领域的巨大进步”“值得关注的里程碑”&#xff01;究竟是什么样的成果值得这样的赞誉呢&#xff1f; 该成果就是中国科学院院士、清…

vue3 前端实现导出下载pdf文件

这样的数据实现导出 yourArrayBufferOrByteArray 就是后端返回数据 // 创建Blob对象const blob new Blob([new Uint8Array(res)], { type: application/pdf })// 创建一个表示该Blob的URLconst url URL.createObjectURL(blob);// 创建一个a标签用于下载const a document.cr…

Vulnhub项目:Thales:1

1、靶机地址 靶机地址&#xff1a;Thales: 1 ~ VulnHub 这个靶机在做的时候有两种思路&#xff0c;下面进行详细渗透过程。 2、渗透过程 来来来&#xff0c;搞起&#xff01;目标56.162&#xff0c;本机56.160 探测&#xff0c;探测&#xff0c;22&#xff0c;8080&#xf…

位置参数

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 位置参数也称必备参数&#xff0c;是必须按照正确的顺序传到函数中&#xff0c;即调用时的数量和位置必须和定义时是一样的。 &#xff08;1&#x…

Java电商平台-开放API接口签名验证(小程序/APP)

说明&#xff1a;在实际的生鲜业务中&#xff0c;不可避免的需要对外提供api接口给外部进行调用. 这里就有一个接口安全的问题需要沟通了。下面是干货: 接口安全问题 请求身份是否合法&#xff1f; 请求参数是否被篡改&#xff1f; 请求是否唯一&#xff1f; AccessKey&am…

利用“记忆化搜索“解斐波那契数

一、题目描述 求第 n 个斐波那契数。 二、 利用"记忆化搜索"解斐波那契数 什么是记忆化搜索&#xff1f;记忆化搜索就是带有备忘录的递归。 我们先来看一下使用递归来解斐波那契数的这个过程&#xff0c;假设求第5个斐波那契数F(5)。 由图可见&#xff0c;要重复计…

P3881

最小值最大 二分&#xff1a;枚举两个牛之间的最小距离&#xff0c;左端点是1&#xff0c;右端点是篱笆总长度。 Check数组&#xff1a; 如果两头牛之间距离是Mid不合法&#xff0c;则返回0&#xff08;false&#xff09;&#xff1b; 如果两头牛之间距离是Mid合法&#xf…

【AVL Design Explorer DOE】

AVL Design Explorer DOE 1、关于DOE的个人理解2、DOE参考资料-知乎2.1 DOE发展及基本类型2.2 DOE应用场景2.3 Mintab 中的 DOE工具3、AVL Design Explorer DOE示例 1、关于DOE的个人理解 仿真和试验一样&#xff0c;就像盲人摸象&#xff0c;在不知道大象的全景之前&#xff…

【Leetcode每日一题】 综合练习 - 组合(难度⭐⭐)(78)

1. 题目解析 题目链接&#xff1a;77. 组合 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 题目要求我们从 1 到 n 的整数集合中选择 k 个数的所有组合&#xff0c;且组合中的元素不考虑顺序。这意味着集合 [1, 2] 和…

【Elasticsearch】IK分词器的下载及使用

安装IK分词器 网址&#xff1a;https://github.com/infinilabs/analysis-ik 3.1.在线安装ik插件&#xff08;较慢,不推荐&#xff09; # 进入容器内部 es为容器名称 docker exec -it es /bin/bash# 在线下载并安装 7.17.21为镜像版本要与之前保持一致 ./bin/elasticsearch-pl…

C++_list简单源码剖析:list模拟实现

文章目录 &#x1f680;1. ListNode模板&#x1f680;2. List_iterator模板(重要)&#x1f331;2.1 List_iterator的构造函数&#x1f331;2.2 List_iterator的关于ListNode的行为 &#x1f680;3. Reverse_list_iterator模板(拓展)&#x1f680;4. List模板(核心)&#x1f331…

stack和queue(1)

一、stack的简单介绍和使用 1.1 stack的介绍 1.stack是一种容器适配器&#xff0c;专门用在具有先进后出&#xff0c;后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入和弹出操作。 2.stack是作为容器适配器被实现的&#xff0c;容器适配器即是…

复习leetcode第二题:两数相加

本文会给出笔者自己的解答&#xff08;代码较为冗余&#xff0c;其实就是屎山代码&#xff09;以及优秀代码的解析 下图是题目 解法1&#xff08;笔者所使用的办法&#xff09;&#xff1a; 解题思路&#xff1a; 以下思路是基于示例1&#xff08;上图&#xff09;思考的 步骤…