最近在学习CTF中Crypto,整理一些关于RSA的知识点,以及在以往比赛中出现的题目。
完美的密码技术因为有不完美的人类参与而无法实现完美的安全性。

简单介绍RSA

RSA是1977年由 罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼 (Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的,三个人名字要有印象,有些题目会用这三个名字,这样可以帮助我们快速判断题目。

RSA公开密钥密码体制的原理是:基于数论,我们能知道随便找两个大素数比较简单,但是如果给定两个大素数的乘积来进行因式分解是及其困难的,因此可以将乘积公开作为加密密钥。

即使 RSA 算法目前来说是安全可靠的,但是错误的应用场景,错误的环境配置,以及错误的使用方法都会导致 RSA 的算法体系出现问题,从而也诞生出针对各种特定场景下的 RSA 攻击方法

RSA公钥密码

RSA公钥密码体制描述如下:
1)选取两个大素数p和q,p和q保密
2)计算n=pq,φ(n)=(p-1)(q-1),n公开,φ(n)(欧拉函数值)保密
3)随机选取正整数 1<e<φ(n),满足gcd(e,φ(n)) = 1,e是公开的加密密钥
4)计算d,满足ed≡1(modφ(n)),d是保密的解密密钥

加密变换:c = m^e mod n
解密变换:m = c^d mod n

虽然n,e 是公开的,但是要想知道 d 的值,必须要将 n 分解来计算出 n 的欧拉函数值,而 n 是两个大素数 p,q 的积, 前面说过分解是及其困难的。 但是对于特定的情况可以使用特殊方法进行分解。
上文以及下文会涉及到一些具体的数论知识,例如:中国剩余定理,同余求余运算,欧拉函数等,大家可以自行查询或者通过《信息安全数学基础》或《现代密码学》进行自学,本文主要针对CTF比赛中关于RSA常见的题型讲解。

gmpy2

python中的一个数论库,本文一些题目的脚本几乎都是基于这个进行编写。可以自行查询。
安装方法pip install gmpy2

CTF中RSA题目常见类型

最最最简单

解决 RSA 题目最简单,最暴力,就是直接分解 n。如果能够将 n 分解成功,得到 p,q 的取值,那么可求φ(n). φ(n)=(p-1)(q-1)
利用e,d 与 n 的欧拉函数满足 ed≡1(modφ(n))
通过欧几里得算法可以通过 e 与 n 的欧拉函数值从而求出 d,计算出解密密钥。
所以在知道 e,p,q 的情况下,就可以解出 d(其实啥都给了,就让你代数计算了)

例题

p = 3487583947589437589237958723892346254777
q = 8767867843568934765983476584376578389
e = 65537 求d?

import gmpy2
p = 3487583947589437589237958723892346254777
q = 8767867843568934765983476584376578389
e = 65537
print gmpy2.invert(e, (p-1)*(q-1))

直接分解 n

素数分解问题是困难的,但是可以暴力分解。通常意义上来说,一般认为 2048bit 以上的 n 是安全的。现在一般的公钥证书都是 4096bit 的证书。
针对大整数的分解有很多种算法,性能上各有优异,有 Fermat 方法,Pollard rho 方法,试除法,以及椭圆曲线法,连分数法,二次筛选法,数域分析法等
推荐一个大整数素分解的网站http://www.factordb.com/
通过在网站上输入 n 的值,如果可以分解或者之前分解成功过,那么我们可以直接得到 p 和 q。然后利用前面方法求解得到密文

例题

2020-CSICTF-Crypto-little RSA
此题可以在CTF-hub上找到
题目包含一个flag.zip 有加密密码,一个enc.txt
ent.txt中的数据

c=32949
n=64741
e=42667

那么我们就可以利用网站将n分解然后使用脚本解密

import gmpy2
c = 32949
n = 64741
e = 42667
p = 101
q = 641
phi = (p - 1) * (q - 1)  # φ(n)
d = gmpy2.invert(e, phi)
a = pow(c, d, n)  # c的d次方 mod n
print(a)

输出a的结果18429 便是flag.zip的解压密码,然后解压后就是flag的文本文件
flagcsictf{gr34t_m1nds_th1nk_4l1ke}

利用公约数分解 n

如果在两次加密过程中使用的n1和n2具有相同的素因子,那么可以利用欧几里得算法直接将n1和n2分解。通过欧几里得算法可以直接求出n1和n2的一个最大公约数p:
gcd(n1,n2)=p
这样的话
q1 = n1 / p
q2 = n2 / p

例题

**2020-BJDCTF-Crypto-rsa **
因为题目已经提示了e=52361 那么我们先直接用
从题目附件的task,py提取所需数据

import gmpy2c1 = 12641635617803746150332232646354596292707861480200207537199141183624438303757120570096741248020236666965755798009656547738616399025300123043766255518596149348930444599820675230046423373053051631932557230849083426859490183732303751744004874183062594856870318614289991675980063548316499486908923209627563871554875612702079100567018698992935818206109087568166097392314105717555482926141030505639571708876213167112187962584484065321545727594135175369233925922507794999607323536976824183162923385005669930403448853465141405846835919842908469787547341752365471892495204307644586161393228776042015534147913888338316244169120
n1 = 13508774104460209743306714034546704137247627344981133461801953479736017021401725818808462898375994767375627749494839671944543822403059978073813122441407612530658168942987820256786583006947001711749230193542370570950705530167921702835627122401475251039000775017381633900222474727396823708695063136246115652622259769634591309421761269548260984426148824641285010730983215377509255011298737827621611158032976420011662547854515610597955628898073569684158225678333474543920326532893446849808112837476684390030976472053905069855522297850688026960701186543428139843783907624317274796926248829543413464754127208843070331063037
c2 = 97915337055253515349847745972087732981120468820838754382612258213240421484845495472248708665806140879522380502220299761352201473698345
n2 = 12806210903061368369054309575159360374022344774547459345216907128193957592938071815865954073287532545947370671838372144806539753829484356064919357285623305209600680570975224639214396805124350862772159272362778768036844634760917612708721787320159318432456050806227784435091161119982613987303255995543165395426658059462110056431392517548717447898084915167661172362984251201688639469652283452307712821398857016487590794996544468826705600332208535201443322267298747117528882985955375246424812616478327182399461709978893464093245135530135430007842223389360212803439850867615121148050034887767584693608776323252233254261047
e = 52361
p = gmpy2.gcd(n1, n2)
q = n1 // p
phi = (p - 1) * (q - 1)d = gmpy2.invert(e, phi)flag = pow(c1, d, n1)print(bytes.fromhex(hex(flag)[2:]))

最终flag为BJD{p_is_common_divisor}
当然e如果没有提示呢,e小于100000,又有pow(294,e,n),可以通过爆破e的取值很快得到e,代码如下

output=381631268825806469518166370387352035475775677163615730759454343913563615970881967332407709901235637718936184198930226303761876517101208677107311006065728014220477966000620964056616058676999878976943319063836649085085377577273214792371548775204594097887078898598463892440141577974544939268247818937936607013100808169758675042264568547764031628431414727922168580998494695800403043312406643527637667466318473669542326169218665366423043579003388486634167642663495896607282155808331902351188500197960905672207046579647052764579411814305689137519860880916467272056778641442758940135016400808740387144508156358067955215018
for i in range(100000):res=pow(294,i,n1)if (res==output):print(i)e=ibreak

共模攻击

如果使用了相同的模 n 对相同的明文 m 进行了加密,我们就可以在不分解 n 的情况下还原出明文 m 的值。即
c1 = m^e1 mod n
c2 = m^e2 mod n
此时不需要分解n,也不需要求解私钥,如果e1和e2互素,那么就可以利用共模攻击利用两个密文和公钥给出的情况下还原密文m

简单的过程,前提条件两个加密指数互质
gcd(e1,e2) = 1,那么s2存在,则:
s1 * e1 + s2 * e2 = 1
因为c1 = m^e1 mod n,c2 = m^e2 mod n
代入化简可以得出 c1^s2 * c2^s2 ≡ m mod n

例题

2020-第五空间智能安全大赛-Crypto-rosb
根据题目给出的py文件,提取所需参数,写出脚本

import gmpy2n = 0xa1d4d377001f1b8d5b2740514ce699b49dc8a02f12df9a960e80e2a6ee13b7a97d9f508721e3dd7a6842c24ab25ab87d1132358de7c6c4cee3fb3ec9b7fd873626bd0251d16912de1f0f1a2bba52b082339113ad1a262121db31db9ee1bf9f26023182acce8f84612bfeb075803cf610f27b7b16147f7d29cc3fd463df7ea31ca860d59aae5506479c76206603de54044e7b778e21082c4c4da795d39dc2b9c0589e577a773133c89fa8e3a4bd047b8e7d6da0d9a0d8a3c1a3607ce983deb350e1c649725cccb0e9d756fc3107dd4352aa18c45a65bab7772a4c5aef7020a1e67e6085cc125d9fc042d96489a08d885f448ece8f7f254067dfff0c4e72a63557
e1 = 0xf4c1158f
c1 = 0x2f6546062ff19fe6a3155d76ef90410a3cbc07fef5dff8d3d5964174dfcaf9daa003967a29c516657044e87c1cbbf2dba2e158452ca8b7adba5e635915d2925ac4f76312feb3b0c85c3b8722c0e4aedeaec2f2037cc5f676f99b7260c3f83ffbaba86cda0f6a9cd4c70b37296e8f36c3ceaae15b5bf0b290119592ff03427b80055f08c394e5aa6c45bd634c80c59a9f70a92dc70eebec15d4a5e256bf78775e0d3d14f3a0103d9ad8ea6257a0384091f14da59e52581ba2e8ad3adb9747435e9283e8064de21ac41ab2c7b161a3c072b7841d4a594a8b348a923d4cc39f02e05ce95a69c7500c29f6bb415c11e4e0cdb410d0ec2644d6243db38e893c8a3707
e2 = 0xf493f7d1
c2 = 0xd32dfad68d790022758d155f2d8bf46bb762ae5cc17281f2f3a8794575ec684819690b22106c1cdaea06abaf7d0dbf841ebd152be51528338d1da8a78f666e0da85367ee8c1e6addbf590fc15f1b2182972dcbe4bbe8ad359b7d15febd5597f5a87fa4c6c51ac4021af60aeb726a3dc7689daed70144db57d1913a4dc29a2b2ec34c99c507d0856d6bf5d5d01ee514d47c7477a7fb8a6747337e7caf2d6537183c20e14c7b79380d9f7bcd7cda9e3bfb00c2b57822663c9a5a24927bceec316c8ffc59ab3bfc19f364033da038a4fb3ecef3b4cb299f4b600f76b8a518b25b576f745412fe53d229e77e68380397eee6ffbc36f6cc734815cd4065dc73dcbcbs = gmpy2.gcdext(int(e1), int(e2))  # 扩展欧几里得算法s1 = s[1]
s2 = s[2]# 求模反元素
if s1 < 0:s1 = -s1c1 = gmpy2.invert(c1, n)elif s2 < 0:s2 = -s2c2 = gmpy2.invert(c2, n)m = pow(c1, s1, n) * pow(c2, s2, n) % nprint(bytes.fromhex(hex(m)[2:]))

flagg0od_go0d_stu4y_d4yd4y_Up

以上是RSA简单入门,当然常见类型还有低加密指数攻击,低解密指数攻,Coppersmith 相关攻击,侧信道,选择明密文攻击等等,我们会在后续文章逐步补充并且会再多整理几道CTF出现过的例题。

es.fromhex(hex(m)[2:]))

flag`g0od_go0d_stu4y_d4yd4y_Up`以上是RSA简单入门,当然常见类型还有低加密指数攻击,低解密指数攻,Coppersmith 相关攻击,侧信道,选择明密文攻击等等,我们会在后续文章逐步补充并且会再多整理几道CTF出现过的例题。

Crypto之RSA(一)相关推荐

  1. 关于Crypto.PublicKey.RSA,在generate后无法被赋值问题

    前言 最近做题的时候有遇到一个问题,就是去利用求解出来的rsa的私钥去生成pem格式的私钥文件.找到网上用的都是先令RSA去generate,然后分别给RSA的n,e,d,p,q参数赋值,再导出私钥. ...

  2. 2022年 HSC-1th中CRYPTO的RSA

    2022年 HSC-1th中CRYPTO的RSA 照例下载附件,是 py 文件: import gmpy2 import sympy from Crypto.Util.number import *f ...

  3. PwnTheBox(Crypto篇)---Rsa(爆破e)

    PwnTheBox(Crypto篇)-Rsa(爆破e) 文章目录 PwnTheBox(Crypto篇)---Rsa(爆破e) 题目描述 rsa基础 直接分解 n 爆破 e 怎么从A绕出? x,y p, ...

  4. 使用Crypto实现RSA算法的数字签名和检验

    总的来说,需要用到的对象有三个: Crypto.PublicKey.RSA:用来生成RSA算法的密钥对象 Crypto.Hash.SHA384:用来获取信息的摘要对象 Crypto.Signature ...

  5. ctfshow crypto funnyrsa3 RSA之dp泄露

    给出了n,c,e,dp,我们可以借助这些来求解pq 网上看了不少wp,对于有关dp的推导总感觉写的不是非常透彻,自己动手写一下,有助于理解. 一开始我以为dp的意思是d*p,那样n=p*q,求n/d* ...

  6. python使用密钥加密的表述_python 利用Crypto进行RSA解密加密文件

    背景:工作需要,部分数据进行了加密传输,对方使用了RSA对密码进行了加密,需要获取到解密的数据. 目标:在已知公钥,私钥的情况下,使用python对其进行解密. RSA加密 一.遇到的问题 收到加密的 ...

  7. 【Crypto】RSA

    目录 1.已知(p,q,e),求d 2.已知(p,q,e,c),求m 3.已知(p,q,dp,dq,c),求m 4.已知(e,dp,n,c),求m 5.已知(n,e1,e2,c1,c2),求m 6.已 ...

  8. 以Crypto++实现RSA加解密二进制数据

    网上一大片讲怎么加解密字符串的,找了大半天也没找到讲加解密二进制数据的,于是自己研究了下,分享给大家. 加解密函数: #include <rsa.h> #include <randp ...

  9. JavaScript的RSA加密库(cryptico、Node-rsa、Crypto、jsrsasign、JSEncrypt)

    JavaScript的RSA加密库 一.Rsa利用openssl生成公钥私钥 1.安装openssl: 2.生成公钥: 3.生成私钥: 二.Cryptico 1.优点: 2.缺点: 3.安装: 4.D ...

最新文章

  1. sql 按字段指定值排序
  2. [codeVS1204] 单词背诵
  3. 存货编码数字_用友T3软件存货编码与存货代码有什么不同?
  4. 3.1.6 基本分页存储管理的基本概念
  5. python3精要(1)-python特点
  6. android RecyclerView EditText 取消自动聚焦
  7. MinGW编译boost库
  8. spring与struts2整合出现错误HTTP Status 500 - Unable to instantiate Action
  9. java二维码小试牛刀
  10. BitTorrent协议与MagNet协议原理
  11. MySQL导入与导出备份详解
  12. MySQL5.6安装流程(MySQL入门)
  13. Linux 上的NetworkManager示例
  14. HTML5响应式个人简历网站模板
  15. CS231n课程笔记翻译:卷积神经网络笔记
  16. 从目标检测数据集中扣出所需类别进行分类
  17. 2018 DDoS攻击加剧,闻“D”色变的无力困境,我们要怎么办
  18. 码元速率与进制数无关
  19. squid代理服务器应用及它的几种代理模式
  20. 力扣--初级算法-1

热门文章

  1. Codeforces Round 861 (Div. 2)-B. Playing in a Casino题解
  2. elasticsearch服务器CPU100%分析
  3. 卓越工程师宣传口号,关键词:实干善为 智创未来;六新工匠 两商领军;六新工匠 智创未来;六新工匠实干巧干善干 技术智慧创优创效创新,再写一篇定位理解,100字以内...
  4. php 主动推送消息,php实现微信公众号主动推送消息
  5. 【机器学习 Alink开源】10分钟了解下阿里开源机器学习平台alink
  6. html生成无序列表,CSS无序列表创建的标准菜单效果代码
  7. jsp判断请求来自手机代码学习
  8. 2020-11-08 Windows应用程序设计作业(Python版实现)(五)综合作业 - 汉字版俄罗斯方块+2048
  9. SQLMap工具-使用选项的操作命令功能
  10. 图形处理之Delaunay三角剖分vtkDelaunay2D