Crypto--RSA

最近在学习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分解然后使用脚本解密


image
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 gmpy2

c1 = 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=i
        break

共模攻击

如果使用了相同的模 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 gmpy2

n = 0xa1d4d377001f1b8d5b2740514ce699b49dc8a02f12df9a960e80e2a6ee13b7a97d9f508721e3dd7a6842c24ab25ab87d1132358de7c6c4cee3fb3ec9b7fd873626bd0251d16912de1f0f1a2bba52b082339113ad1a262121db31db9ee1bf9f26023182acce8f84612bfeb075803cf610f27b7b16147f7d29cc3fd463df7ea31ca860d59aae5506479c76206603de54044e7b778e21082c4c4da795d39dc2b9c0589e577a773133c89fa8e3a4bd047b8e7d6da0d9a0d8a3c1a3607ce983deb350e1c649725cccb0e9d756fc3107dd4352aa18c45a65bab7772a4c5aef7020a1e67e6085cc125d9fc042d96489a08d885f448ece8f7f254067dfff0c4e72a63557
e1 = 0xf4c1158f
c1 = 0x2f6546062ff19fe6a3155d76ef90410a3cbc07fef5dff8d3d5964174dfcaf9daa003967a29c516657044e87c1cbbf2dba2e158452ca8b7adba5e635915d2925ac4f76312feb3b0c85c3b8722c0e4aedeaec2f2037cc5f676f99b7260c3f83ffbaba86cda0f6a9cd4c70b37296e8f36c3ceaae15b5bf0b290119592ff03427b80055f08c394e5aa6c45bd634c80c59a9f70a92dc70eebec15d4a5e256bf78775e0d3d14f3a0103d9ad8ea6257a0384091f14da59e52581ba2e8ad3adb9747435e9283e8064de21ac41ab2c7b161a3c072b7841d4a594a8b348a923d4cc39f02e05ce95a69c7500c29f6bb415c11e4e0cdb410d0ec2644d6243db38e893c8a3707
e2 = 0xf493f7d1
c2 = 0xd32dfad68d790022758d155f2d8bf46bb762ae5cc17281f2f3a8794575ec684819690b22106c1cdaea06abaf7d0dbf841ebd152be51528338d1da8a78f666e0da85367ee8c1e6addbf590fc15f1b2182972dcbe4bbe8ad359b7d15febd5597f5a87fa4c6c51ac4021af60aeb726a3dc7689daed70144db57d1913a4dc29a2b2ec34c99c507d0856d6bf5d5d01ee514d47c7477a7fb8a6747337e7caf2d6537183c20e14c7b79380d9f7bcd7cda9e3bfb00c2b57822663c9a5a24927bceec316c8ffc59ab3bfc19f364033da038a4fb3ecef3b4cb299f4b600f76b8a518b25b576f745412fe53d229e77e68380397eee6ffbc36f6cc734815cd4065dc73dcbcb

s = gmpy2.gcdext(int(e1), int(e2))  # 扩展欧几里得算法

s1 = s[1]
s2 = s[2]

# 求模反元素
if s1 < 0:
    s1 = -s1
    c1 = gmpy2.invert(c1, n)

elif s2 < 0:
    s2 = -s2
    c2 = gmpy2.invert(c2, n)

m = pow(c1, s1, n) * pow(c2, s2, n) % n

print(bytes.fromhex(hex(m)[2:]))

flagg0od_go0d_stu4y_d4yd4y_Up

以上是RSA简单入门,当然常见类型还有低加密指数攻击,低解密指数攻,Coppersmith 相关攻击,侧信道,选择明密文攻击等等,我们会在后续文章逐步补充并且会再多整理几道CTF出现过的例题,还有一些常见类型的变形,比如RSA共模 e1,e2不互素怎么办,我们都会在后续介绍。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容