【密码学RSA】DASCRF八月挑战赛_ezRSA

1.nc远程连接:

nc node4.buuoj.cn 29831

2.查看题目task:

from secret import flag
from Crypto.Util.number import *
from random import getrandbits
from hashlib import sha256


class EzRsa:
    def __init__(self):
        self.E = 0x10001
        self.P = getPrime(1024)
        self.Q = getPrime(1024)
        while GCD((self.P-1)*(self.Q-1), self.E) != 1:
            self.Q = getPrime(1024)
        self.N = self.P*self.Q

    def encrypt(self):
        f = getrandbits(32)
        c = pow(f, self.E, self.N)
        return (f, c)

    def encrypt_flag(self, flag):
        f = bytes_to_long(flag)
        c = pow(f, self.E, self.N)
        return c


def proof():
    seed = getrandbits(32)
    print(seed)
    sha = sha256(str(seed).encode()).hexdigest()
    print(f"sha256({seed>>18}...).hexdigest() = {sha}")
    sha_i = input("plz enter seed: ")
    if sha256(sha_i.encode()).hexdigest() != sha:
        exit(0)


if __name__ == "__main__":
    proof()
    print("welcome to EzRsa")
    print("""
    1. Get flag
    2. Encrypt
    3. Insert
    4. Exit
    """)
    A = EzRsa()
    coin = 5
    while coin > 0:
        choose = input("> ")
        if choose == "1":
            print(f"pow(flag,e,n) = {A.encrypt_flag(flag)}\ne = 0x10001")
            exit(0)
        elif choose == "2":
            f, c = A.encrypt()
            print(f"plain = {f}\ncipher = {c}")
            coin -= 1
        elif choose == "3":
            q = getrandbits(1024)
            n = A.P*q
            f = getrandbits(32)
            c = pow(f, 0x10001, n)
            print(f"plain = {f}\ncipher = {c}")
            coin -= 1
        elif choose == "4":
            print("bye~")
        else:
            print("wrong input")
    print("Now you get the flag right?")

3.分析过程:

5个硬币,5次选择机会,最终目标是获取choice1中的flag=pow(c,d,n)。

所以需要求出p,q,n,在choice3中可以看到A.P来自与EzRsa这个类,因为种子固定,所以每次的A.P都相同,由于p一般为kp比较大,无法爆破,所以可以根据选择两次3,求最大公约数的方式求kp:

推导过程:
c31=m31^e%n
   =m31^e-k1n
   =m31^e-k1*p*q1
c32=m32^e%n
   =m32^e-k2n
   =m32^e-k2*p*q2

所以:
k1*p*q1=m31^e-c31
k2*p*q2=m32^e-c32

所以,通过欧几里得算法求公约数:
gcd(m31^e-c31,m32^e-c32)
p为公约数,如果k1和k2互素,公约数则为p;不互素,公约数为kp

同理,选择两次choice2,求出公约数n:

推导过程:
c21=m21^e%n
   =m21^e-k1n

c22=m22^e%n
   =m22^e-k2n

所以:
k1n=m21^e-c21
k2n=m22^e-c22
n为公约数,如果k1和k2互素,公约数则为n;不互素,公约数为kn

所以需要写循环判断k1和k2是否互素

4.exp:该脚本先计算出kn的k值,然后,注释掉n的函数调用,直接计算n=kn//3

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

m32 = 3323861755
c32 = 3189600455343045434080347477377637509639599093851483905469324364325280015612695035974460965906143466590067058820022037215171320039106501227090699765870079884516902376220489075658195797239624361978029353515372989346970685866580974883414497877056461544490050501294946867616806663820642287073662764555736921469660321660426415536232186568006099805750142302915837627738705008958091128158815612024425841213331717831045875324620701104247050280930690805178761910513823571401611581282576469913633179017318736801189219784253867305021130959131652677457283221377437538402795936136989234771438450126125288004100790674284118174245
m31= 2905310453
c31 = 2120565633610951077941408013358952516811861122789219625789934408897427578162721586466656928552605179729112639291741870081373303246269810410969173072036339930701012508737104606501941337497152394658336331350370845697411306670862802768866713312047784662830052433356420834207281572915360197159247150939609324108293693018061893203755507115913362099001088934356822665537267849572444146470179382854418790912627138058547478480232826854971403641267130040586290801692807074115787085791944837845074067423725376086847943520064232425683298621813358060198654633324986211798423617076959313361715754819102009643187348797398069765786
m22 = 616858868
c22 = 605563881409216330847669526462868481426198351625605143143266962817465835792648878756702619432683534965294072375800100712154114554144606972279812467636022968304993315143809363224197826056890452379708490559111716835856182100890741862972071504150399911275224860125286182474924846242400198673855143951141264794223514979858497124028733290900826044914905952895104924912862844974767484534446183511008350846185437719281973039843561565537371670697761880512290430164465139031441558044768964316607817344296736994028669368360274702222505694753759958463980495408150250582691160167727479506569386708621967079259357962735901575139
m21 = 3634632521
c21 = 1413535001511989764430561420750992223439084726181291612751329294086131401295033206111884399389132757372373421411093951829105632559387812507997223640686969347737187572441734790693531411682686131585735490815603314930183293261226164898661688481751362320548282386718963976466919534178881782027426154450358177644252281757378349193675527673605562843736598993426404303110768026085252784297480654365997826769452386577613167377385502329569051341885040492915597541098427570666977195876149288107417212891503323773577021450417252250704450118861155868563857637982731085076955391888769802874741035176160901513860209444453095501149
c =  12220699867583389713189337563070388502884711983567881601567164519070090130746870615727797479813679364921988322629180343147954990329314605951355031756186402654953156028344200485817682150494402566738965512529164151673986717059696437660614129716871283169617251674891552386020328591497805753589519339410450250717056044384508363366278793241787814076134681307520678937377712136397588221480066278249164880616307557346834844908222674060238693168924763195094750799943451157049128567967860995613642063540796703533664520023681811737488844905521105858034719053389672368379599366604446837961399110377113163256957097411924626051947
e = 0x10001

import gmpy2

def p_def(p):
    k=1
    while 1:
        if gmpy2.is_prime(p):
            print(p)
            print(k)
            return p
        elif p % (k) == 0 and k != 1:
            p=p//k
            print(k)
        else:
            k+=1

kp=gmpy2.gcd(m31**e-c31,m32**e-c32)
# print(kp)
#print(gmpy2.is_prime(kp))
p=p_def(kp)
# print(p)
#print(gmpy2.is_prime(p))

kn=gmpy2.gcd(m21**e-c21,m22**e-c22)
#print(kn)
#kn=p_def(kn)
n=kn//3
q=n//p
print(gmpy2.is_prime(q))

phi_n=(p-1)*(q-1)
d=gmpy2.invert(e,phi_n)
m=pow(c,d,n)
print(libnum.n2s(int(m)))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值