BUUCTF 每日打卡 2021-8-30

引言

马上开学了,摸了
打了DASCTF八月赛,比赛结束前1小时参赛,结果解题最多的题没做出来(啊这)
在这里插入图片描述

[DASCTF八月赛 2021]easymath

比赛的时候没做出来,后来Pheonix大佬告诉了我解法
给的代码很短:

assert(len(open('flag.txt', 'rb').read()) < 50)
assert(str(int.from_bytes(open('flag.txt', 'rb').read(), byteorder='big') << 10000).endswith(
    '1862790884563160582365888530869690397667546628710795031544304378154769559410473276482265448754388655981091313419549689169381115573539422545933044902527020209259938095466283008'))

做到时候很疑惑,把给的数字转换成二进制也就五百多位,哪来左移10000位呢
也可以有这样的关系式: e n d = f l a g ∗ 2 10000   m o d   1 0 175 end = flag * 2^{10000}\space mod \space 10^{175} end=flag210000 mod 10175
其中175是给的结尾部分的十进制位数,模 1 0 175 10^{175} 10175的目的是为了求 2 10000 2^{10000} 210000的逆元,得到flag
解密代码如下:

from Crypto.Util.number import *

end = 1862790884563160582365888530869690397667546628710795031544304378154769559410473276482265448754388655981091313419549689169381115573539422545933044902527020209259938095466283008
# end = flag*2**{10000} mod 10^{175}
t = inverse(2**10000, 10**175)
m = long_to_bytes(((end * t) % 10**175) // GCD(2**10000, 10**175))
print(m)

结果为:
在这里插入图片描述
这里值得注意的是,如果用t = gmpy2.invert(2**10000, 10**175),则会报错:
在这里插入图片描述
那为什么用Crypto.Util.number库的inverse就行呢?还有,为什么要除GCD(2**10000, 10**175)呢?
模逆元的定义中有这样一段话:
整数 a 对模数 n 之模逆元存在的充分必要条件是 a 和 n 互素,若此模逆元存在,在模数 n 下的除法可以用和对应模逆元的乘法来达成,此概念和实数除法的概念相同
本题中 1 0 175 10^{175} 10175 2 10000 2^{10000} 210000显然不互素,inverse先分离出了GCD(2**10000, 10**175),才可以进行模逆元计算,因此最后要除GCD(2**10000, 10**175)

[DASCTF八月赛 2021]let’s play with rsa~

加密代码如下:

from sympy import isprime,nextprime
from Crypto.Util.number import getPrime as getprime ,long_to_bytes,bytes_to_long,inverse
flag='flag{***************}'

def play():
    p=getprime(1024)
    q=getprime(1024)

    n=p*q
    e=65537

    print "Hello,let's play rsa~\n"
    print 'Now,I make some numbers,wait a second\n'
    n1=getprime(200)
    n2=getprime(200)
    number=n1*n2
    print "Ok,i will send two numbers to you,one of them was encoded.\n"
    print "Encode n1:%d,\n"%(pow(n1,e,n))
    print "And n2:%d.\n"%n2

    print "Information that can now be made public:the public key (n,e):(%d,%d)\n"%(n,e)
    while True:
        try:
            c=int(raw_input("ok,now,tell me the value of the number (encode it for safe):"))
        except:
            print "Sorry,the input is illeagal, and the integer is accept~"
        else:
            break
    d=inverse(e,(p-1)*(q-1))
    m=pow(c,d,n)
    if m==number:
        print "It's easy and interesting,didn't it?\n"
        print "This is the gift for you :"+flag
    else:
        print "Emmmmm,there is something wrong, bye~\n"

if __name__ == '__main__':
    play()

先随机生成了两个数n1,n2,然后给了我们pow(n1,e,n)n2,让我们传进去一个c使得c最后RSA解密后与n1*n2相等
那直接把n2加密之后和pow(n1,e,n)相乘,传进去不就行了吗(啊这)
生成c代码如下:

c1 = 
n2 = 
n = 
e = 65537
c2 = pow(n2, e, n)
print(c1*c2 % n)

把结果传入即可

[DASCTF八月赛 2021]ezRSA

加密代码如下:

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?")

输入1,能得到加密后的flag和e
输入2,用EzRsa中的公钥记为nt,随机加密一个数,得到明文和密文
输入3,用EzRsa中的p和一个随机生成的q生成新的公钥记为nk,随机加密一个数,得到明文和密文
我们可以利用明文,e和密文得到公钥
由于有四次机会,可以得到一对nt和一对nk,由此得到输入2中的 n 1 = g c d ( n t 1 , n t 2 ) n1 = gcd(nt1, nt2) n1=gcd(nt1,nt2)和输入3中的 n 2 = g c d ( n k 1 , n k 2 ) n2 = gcd(nk1, nk2) n2=gcd(nk1,nk2),由于n1n2有公因子p,得到 p = g c d ( n 1 , n 2 ) p = gcd(n1,n2) p=gcd(n1,n2),所以可以分解EzRsa中的n,得到flag
至于proof()部分,不知道为什么,他把seed都print出来了,直接复制就行了
解密代码如下:

from Crypto.Util.number import *
import gmpy2

ck1 = 10802736552802052334675431350693279487373514975583856720432908395157316583920875453552436496142443616668241018608905018877443641691597372943993746940796864088947110039691619330329829547914610310034042851600736815309651502714085552791205969637596625163884286216655679274373500381744546328590741571307166491219684988090657352142159038206188374695832891006030375956054657085966865212601720744964287594027579678929262839778089899170206998082556473498244863021611505400743727905185153354589976465321853027253539821633361185313034408565005594026376244077003811333923401071515437065293484027335646730805732706266190998912717
mk1 = 3467298486
ck2 = 7952426014817800345542743164212370465256522007694059040467262294139883798321376411423890059270181570060140439911489431487610048706425767050670076985945266595950167706634614499687295626618973683170430839755441335740665931270096392149318526814329218978695464692209823256428215580327499120933284877331428541567646264394511614834203230064225146095541013932153997347325545390454756521012184772766523934716861371813919366599810016530328522084402639154774851578047016291472426451432937369700785642186037817214135023341172743718729742706979406927034574357730393647164709577350234290575266246455335325036550238459460266826777
mk2 = 2637805758
ct1 = 5258297249437233269252734235581546483712740587856019368263741383010451771667214261941296958987255470129584667269164992391194597613632284942804492915958705615338348819026219002542835081068188830987745841778711674448286841103336689060336238552664704124260432965541782948103450178133013110447584887798935485919036836447185053522888046907188507552263118079180956315895262605349789171527309529542909346214121425645357866293754412692643751802750793196774012389022291591637648327944593680206557486483425679654293733112064106916782478544290625173885362276421903124336254498078544284381979906370583318057836106074195007704645
mt1 = 4018514725
ct2 = 2216710613849759291749271001172813296813995296942937937269459242162726262423838768504690540899513401365048563136110961705376280976325200801225641366994647978361247640072336671999168903599506081309580038964520354319361272932687736277969229054373565318758544270975463383927123441762751596885765477383664317818484566431143004646542531904764815747154445292706021915390615940095755639417784345435399786628193680479805174721200711052159068548732143161630778867220968156180570439298242013424813121308759181410582014316563549742660719169563010989100847264028027523510004333399915674385321042096844588069039993247180371045195
mt2 = 3768336235
e = 0x10001
c = 2409589959567577978959459059612176821685774169484662256361511224239193757207995235364470043362762616376254680228672727010474530311597231338182077689977346876997505890770280261284937438407769714519654847286916170373152881118623219276049395838329185415833388821874689670453791866822667341256546099953050403653918769534241514590069310425374668208283548693974017032984604264320169879760335946006653980827443567622501985484127746767154218399238266814865552396320059488020365523603371608242845046716068485196590482585388538864834136370002751749734914128047230447149334621639953462809629563555690666798206156581413136941807

nk1 = pow(mk1, e) - ck1
nk2 = pow(mk2, e) - ck2
n1 = gmpy2.gcd(nk1, nk2)
print(n1)
nt1 = pow(mt1, e) - ct1
nt2 = pow(mt2, e) - ct2
n2 = gmpy2.gcd(nt1, nt2)
print(n2)
p = gmpy2.gcd(n1, n2)
print(p)
print(gmpy2.is_prime(p))
q = n1 // p
print(q)
print(gmpy2.is_prime(q))
phi = (p-1)*(q-1)
d = inverse(e, phi)
m = pow(c, d, p*q)
print(long_to_bytes(m))

在这里插入图片描述
另外,发现Crypto.Util.number中的GCD()函数比gmpy2gcd()计算较大数时慢很多

结语

希望继续坚持

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值