buuctf的rsa题解

buuctf rsa小总结(第一页)

前言:

记录一下自己的学习过程

感谢博主:

有借鉴CTFer菜菜的文章,他的数学原理推导过程很有帮助

学习前置:

需要库(自行下载):gmpy2,rsa还有一些进制转文本的库

基础知识:c密文,m明文,e公钥(随机),q,p是随机的两个素数,n=p*q

私钥d与公钥e的关系:(de)%(p-1)(q-1)=1

m=c^d%n,n=qp,(de)%(p-1)*(q-1)=1(用以求逆元)

备注:进阶知识有补充,最后需要转文字

1.RSA

在一次RSA密钥对生成中,假设p=473398607161,q=4511491,e=17 求解出d作为flga提交,

求逆元:gmpy2.invert(e,(p-1)*(q-1)) 会返回d的值

上代码

import gmpy2
p = 473398607161
q = 4511491
e = 17
d = int(gmpy2.invert(e,(p-1)*(q-1)))
print(d)

2.rsasa

题目

p =  9648423029010515676590551740010426534945737639235739800643989352039852507298491399561035009163427050370107570733633350911691280297777160200625281665378483
q =  11874843837980297032092405848653656852760910154543380907650040190704283358909208578251063047732443992230647903887510065547947313543299303261986053486569407
e =  65537
c =  83208298995174604174773590298203639360540024871256126892889661345742403314929861939100492666605647316646576486526217457006376842280869728581726746401583705899941768214138742259689334840735633553053887641847651173776251820293087212885670180367406807406765923638973161375817392737747832762751690104423869019034

根据公式:m=c^d%n可得思路:先求d,再求m

上代码:

import gmpy2
p = 9648423029010515676590551740010426534945737639235739800643989352039852507298491399561035009163427050370107570733633350911691280297777160200625281665378483
q = 11874843837980297032092405848653656852760910154543380907650040190704283358909208578251063047732443992230647903887510065547947313543299303261986053486569407
e = 65537
c = 83208298995174604174773590298203639360540024871256126892889661345742403314929861939100492666605647316646576486526217457006376842280869728581726746401583705899941768214138742259689334840735633553053887641847651173776251820293087212885670180367406807406765923638973161375817392737747832762751690104423869019034
n = p*q
d = int(gmpy2.invert(e,(p-1)*(q-1)))# 数学意义:(d*e)%(p-1)*(q-1)=1 ==> d=(k*(p-1)*(q-1)+1)/e,求逆元原理
m = pow(c,d,n)      #pow函数用法简单:c^d%n的意思(求幂取模)
print(m)

3.RSA1

题目:

p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229 
q = 12640674973996472769176047937170883420927050821480010581593137135372473880595613737337630629752577346147039284030082593490776630572584959954205336880228469 
dp = 6500795702216834621109042351193261530650043841056252930930949663358625016881832840728066026150264693076109354874099841380454881716097778307268116910582929 
dq = 783472263673553449019532580386470672380574033551303889137911760438881683674556098098256795673512201963002175438762767516968043599582527539160811120550041 
c = 24722305403887382073567316467649080662631552905960229399079107995602154418176056335800638887527614164073530437657085079676157350205351945222989351316076486573599576041978339872265925062764318536089007310270278526159678937431903862892400747915525118983959970607934142974736675784325993445942031372107342103852

这里首先要知道dpdq是什么,下面式子有说明:

这里首先要知道什么是同余(≡)比如a≡b(modn)就表示:两个整数a、b,如果他们同时除以一个自然数n,所得的余数相同,则称a、b对于模m同余,记作a≡b(modn

公式:dp≡d mod (p-1) ,dq≡d mod (q-1) ,m≡c^dmodn

m≡c^dmodn这个公式解释一下:因为m=c^d%n,所以m<n,这样m%n=m,c^d%n=m,同余

m≡c^dmodn就是m=k*n+c^d(k为整数,m小于c^d,这里肯定是负数了)(方程好理解)

就是m=c^d+kpq

对上面的式子同时取余(可以理解为对m=c^d%n两次取余)

得到mp=c^d%p;mq=c^d%q

这里对mp式子进行转换(方便代入):c^d=k*p+mp,再将mq代入

mq≡(k*p+mp)%q,再将两边同时减去mp(数学基本思维:未知数放在等式同一边)

(mq-mp)≡k*p%q

根据rsa基本原理:p,q为素数所以gcd(p,q)=1,敏感的人就发现了,可以对p求逆元:

(mq-mp)*p(-1)≡k%q再根据同余的原理得到:

k≡(mq-mp)p(-1)%q再与上面推导的式子c^d=kp+mp联立

得出:c^d=((mq-mp)p^(-1)%q)p+mp代入公式m≡c^d%n(由从c^d≡m%n而来)

得到m≡(((mq-mp)p^(-1)%q)p+m1)%n(到这里不知道怎么推导的了求佬解决)

推导为m = (((mq-mp)I)%q)p+mp(I为p,q的逆元)

最后仅仅几行代码

import gmpy2
I = gmpy2.invert(p,q) 
mp = pow(c,dp,p)
mq = pow(c,dq,q)               
m = (((mq-mp)*I)%q)*p+mp       #求明文公式
print(print(hex(m)[2:]))  # 转为十六进制

4.RSA2

给了e,n,dp,c

这里给公式:dp≡d mod (p-1);d*e≡1%(p-1)(q-1)

还是数学原理:

公式:m=c^d%n也就是求d

而d的求法也只有一个:逆元:d=gmpy2.invert(e,(p-1),(q-1))

现在知道求了p就可以求出q也就能求d

缩小范围遍历求出p,现在推导p的范围

dpe=ed%(p-1)(由dp≡d mod (p-1)推出)

ed=k(p-1)+dp*e(k为整数)

ed=a(p-1)(q-1)+1(a为整数)(由de≡1%(p-1)(q-1)推出)

联立:

a(p-1)(q-1)+1=k(p-1)+dpe

整理得:(p-1)(a(q-1)-k)+1=dp*e

令x=(a(p-1)-k)

所以dpe=(p-1)x+1

又因为dp<p-1

可以推出x的范围1<x<e

由x=(a(q-1)-k)推出p=(dp*e-1)/x+1

代码实现:

import gmpy2
    for i in range(1, e):  # 在范围(1,e)之间进行遍历
        if (dp * e - 1) % i == 0:
            if n % (((dp * e - 1) // i) + 1) == 0:  # 存在p,使得n能被p整除
                p = ((dp * e - 1) // i) + 1
                q = n // (((dp * e - 1) // i) + 1)
                phi = (q - 1) * (p - 1)  # 欧拉定理
                d = gmpy2.invert(e, phi)  # 求模逆
                m = pow(c, d, n)# 快速求幂取模运算
                print(print(hex(m)[2:]))

5.RSA3

涉及数学知识,扩展欧几里得算法,费马小定理

由数学原理,欧几里得算法可得:e1 * s1 + e2 * s2 = 1

这里s1,s2与e1,e2关系为逆元即

s1=gmpy2.invert(e1,e2)
s2=gmpy2.invert(e2,e1)

m=m%n(明文肯定比n小,相当于m=m)

m = m^(e1s1+e2s2) % n

m = (m^(e1*s1) % n * m^(e2*s1) % n) % n

m = (c1^s1 % n * c2^s2 % n) % n

涉及到gmpy2的函数;gcdext(即扩展欧几里得算法)

上代码:

import gmpy2
r,s1,s2=gmpy2.gcdext(e1,e2)
m=(pow(c1,s1,n)*pow(c2,s2,n))%n
print(print(hex(m)[2:]))

6.RSA

需要网站公钥解析(没网的时候用kali的rsa工具,以后补充)

得到文件

无法打开,添加后缀.txt

打开后得到公钥,公钥解析后拿到e,n

n比较小,直接用网站分解整数n

这时候可以直接用脚本:

 d = gmpy2.invert(e, phi)

也可以用工具,RSA Tool2 by Te!

最后用脚本

import rsa#要导入rsa库
key = rsa.PrivateKey(n,e,d,q,p)        
with open("解压flagenc的地址","rb") as f:  #rb指以二进制读模式,读取密文  
    f = f.read()
    print(rsa.decrypt(f,key))

7.RSAROLL

两个文件

看见括号一般是(n,e)

n很小,用分解网站分解(这里一样可以用kali的工具,以后补充)

得到p,q

再求d = gmpy2.invert(e, phi)

接下来密文盲猜是下面的一长串数字,但是需要一行一行来,很麻烦,直接利用文件读取及strip函数去除\n

,但是注意,这里的每一行数字对应一明文的一个字符,不能合在一起当一个大数字用

上代码:

import gmpy2
n=920139713
e=19
p=18443
q=49891
d=gmpy2.invert(e,(p-1)*(q-1))
flag=''
with open("D:\\火狐\\704796792.txt",'r')as f:#这里要修改为自己的地址
    for i in f.readlines():
        i=i.strip('\n')
        flag+=(chr(pow(int(i),d,n)))
print(flag)

buuctf第一页的RSA解密完毕

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值