buuctf的RSA(一)

1.RSA

根据题目,直接求d

import gmpy2     利用gmpy2 来进行模反运算

e = 17
p = 473398607161
q = 4511491

phi_n = (p - 1) * (q - 1)     # 这里直接求n的欧拉值,
d = gmpy2.invert(e, phi_n)  
# 函数返回的是e模phi_n的模逆元。也就是说,它找到了一个数d,使得e * d mod phi_n = 1
print(d)

还可以用RSA的工具来解决这个问题。

2.rsarsa

已经知道了p,q,e,c   应该是要进行密文的解密

先看一下,从网上随便找的脚本,

运行得到一串奇怪的东西,分析一下原因,

         填充问题,在RSA加密中,明文通常会被填充以匹配模数 n 的长度。如果直接对解密后的整数 m 使用 long_to_bytes,您可能会得到包含填充的字节串,而不是原始的明文。您需要使用适当的填充方案(如PKCS#1 v1.5或OAEP)来去除这些填充字节。

        编码问题,原始明文在加密前通常是作为被编码的字节串(如使用UTF-8)。但是,long_to_bytes 仅仅是将整数转换为字节串,而不涉及任何编码。因此,如果原始明文是文本,可能还需要将字节串解码为字符串(使用正确的编码)。

   

正确的为:

代码:


e = 65537
p = 9648423029010515676590551740010426534945737639235739800643989352039852507298491399561035009163427050370107570733633350911691280297777160200625281665378483
q = 11874843837980297032092405848653656852760910154543380907650040190704283358909208578251063047732443992230647903887510065547947313543299303261986053486569407
n = p * q
# 密文
C = 83208298995174604174773590298203639360540024871256126892889661345742403314929861939100492666605647316646576486526217457006376842280869728581726746401583705899941768214138742259689334840735633553053887641847651173776251820293087212885670180367406807406765923638973161375817392737747832762751690104423869019034

d = gmpy2.invert(e, (p - 1) * (q - 1))
print(d)
# 求明文
m = pow(C, d, n)  # 快速求幂取模运算
print(m)

flag为明文

3.RSA1 和 RSA2

        根据题目,已经知道了p,q,dp,dq,c

dp,dq  是dp-1q-1的模逆元(在RSA中,它们通常用于快速解密,因为使用它们可以避免计算d,这是一个大数,可能会导致性能下降)。接下来,我们要使用中国剩余定理(CRT)变种

import gmpy2
from Crypto.Util.number import long_to_bytes   #将长整数转化为字节字符串

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

I = gmpy2.invert(q, p) 
 # 计算了q模p的模逆元。在数学上,这意味着I是一个整数,使得q * I mod p = 1。注意,这里的I并不是中国剩余定理中常用的h(h是p模q的模逆元),但在这个上下文中,我们只需要I

mp = pow(c, dp, p)   #使用模幂运算,计算c的dp次方模p的结果。
mq = pow(c, dq, q)   #使用模幂运算,计算c的dq次方模q的结果。

m = (((mp-mq) * I) % p) * q + mq      #CRT的一个变种,用于从mp和mq中恢复明文m



print(long_to_bytes(m))    #解密后的整数m转换为字节字符串并输出



import gmpy2

e = 65537
n = 248254007851526241177721526698901802985832766176221609612258877371620580060433101538328030305219918697643619814200930679612109885533801335348445023751670478437073055544724280684733298051599167660303645183146161497485358633681492129668802402065797789905550489547645118787266601929429724133167768465309665906113
dp = 905074498052346904643025132879518330691925174573054004621877253318682675055421970943552016695528560364834446303196939207056642927148093290374440210503657
c = 140423670976252696807533673586209400575664282100684119784203527124521188996403826597436883766041879067494280957410201958935737360380801845453829293997433414188838725751796261702622028587211560353362847191060306578510511380965162133472698713063592621028959167072781482562673683090590521214218071160287665180751

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(bytes.fromhex(hex(m)[2:]))  # 16进制转文本,详细在下面


     中国剩余定理(CRT):

        用python来实现,

    交换环在研究生时学

       详细在:中国剩余定理 - OI Wiki

4.RSA3(共模攻击)

     现在知道了,c1,c2,n,e1,e2,先来了解

共模攻击是指用两个及以上的公钥(n, e)来加密同一条信息m

继续使用CRT

不过使用CRT,我们要先来检查e1,e2是否互质,根据互质时,gcd(e1,e2)=1

import math  
  
e1 = 11187289  
e2 = 9647291  
  
# 检查e1和e2是否互质  
gcd_value = math.gcd(e1, e2)  
if gcd_value == 1:  
    print("e1和e2互质")  
else:  
    print("e1和e2不互质,无法使用CRT进行解密")

得到e1,e2互质

   

    似乎是明文经过其他密码加密,

   错误:大家可能会想到,得到明文进行再次进行直接解密。比如这题,一看好像是16进制(hex)转字符串,直接上工具,但是结果错误。

  原因:

  • 不同的加密算法:不同的加密算法有不同的加密和解密过程,以及不同的密钥和参数。一个加密算法解密出来的明文可能是完全无意义的、随机的,或者只是针对该加密算法有意义的。这样的明文通常不适合直接用于另一个加密算法的解密过程,除非这两个加密算法有特定的兼容性设计(这在实践中是罕见的)。
  • 密钥不匹配:每个加密算法都依赖于一个或多个密钥来进行加密和解密。一个加密算法使用的密钥与另一个加密算法使用的密钥通常是不同的。因此,即使明文本身是可以理解的,但由于密钥不匹配,使用错误的密钥进行解密也会导致错误的结果。
  • 数据格式和填充:在加密过程中,数据可能需要进行特定的格式转换或填充以满足加密算法的要求。解密过程会移除这些填充或转换数据以恢复原始明文。然而,这些格式转换和填充通常是特定于所使用的加密算法的。因此,将一个加密算法解密出来的明文直接用于另一个加密算法的解密可能会导致问题,因为第二个加密算法可能不理解或无法正确处理这些格式转换和填充。

所以,修改一下最后一句,得到flag

  1. hex(m)     使用  hex()函数将整数 mm转换为十六进制字符串表示。例如,如果 m 是 255,则 hex(m) 返回"0xff" .m 是一位数时,返回为空,即 “”

  2. hex(m)[2:]     使用 Python 的字符串切片功能从 hex(m) 返回的字符串中去掉前两个字符。例如,使hex(m) 返回"ff" .

  3. bytes.fromhex()使用 bytes类的 fromhex()方法将十六进制字符串转换为字节对象。在这个例子中,它将"ff" 转换为字节对象b'\ff'。简单来说就是,直接打印出对象

           但如果 m是一个非正整数或者非常大的整数(其十六进制表示超过了 Python 整数类型的范围),hex(m)可能会返回不同的结果,或者引发异常。

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

补充:

    当e1,e2不互质时,

设gcd(e1, e2) = a,得到s1 * e1 + s2 * e2 = a
即最后求得的m还需要开a次根

a, s1, s2 = gcdext(e1, e2)
m1 = gmpy2.powmod(c1, s[1], n)
m2 = gmpy2.powmod(c2, s[2], n)
m = (m1 * m2) % n

while True:
    if iroot(m, a)[1]:
        m = iroot(m, a)[0]
        print(long_to_bytes(m))
        break
    m += n

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值