[山海关crypto 训练营 day2]

日常鼓励自己:没人会嘲笑竭尽全力的人。

Blinding Light(120 pt)

题目描述

在这里插入图片描述

题目源代码

#!/usr/bin/env python3

from Crypto.Util.number import bytes_to_long, long_to_bytes
from utils import listener

FLAG = "crypto{?????????????????????????????}"
ADMIN_TOKEN = b"admin=True"


class Challenge():
    def __init__(self):
        self.before_input = "Watch out for the Blinding Light\n"

    def challenge(self, your_input):
        if 'option' not in your_input:
            return {"error": "You must send an option to this server"}

        elif your_input['option'] == 'get_pubkey':
            return {"N": hex(N), "e": hex(E) }

        elif your_input['option'] == 'sign':
            msg_b = bytes.fromhex(your_input['msg'])
            if ADMIN_TOKEN in msg_b:
                return {"error": "You cannot sign an admin token"}

            msg_i = bytes_to_long(msg_b)
            return {"msg": your_input['msg'], "signature": hex(pow(msg_i, D, N)) }

        elif your_input['option'] == 'verify':
            msg_b = bytes.fromhex(your_input['msg'])
            msg_i = bytes_to_long(msg_b)
            signature = int(your_input['signature'], 16)

            if msg_i < 0 or msg_i > N:
                # prevent attack where user submits admin token plus or minus N
                return {"error": "Invalid msg"}

            verified = pow(signature, E, N)
            if msg_i == verified:
                if long_to_bytes(msg_i) == ADMIN_TOKEN:
                    return {"response": FLAG}
                else:
                    return {"response": "Valid signature"}
            else:
                return {"response": "Invalid signature"}

        else:
            return {"error": "Invalid option"}


listener.start_server(port=13376)


题目分析

代码大体的作用是,输入一段内容,程序返回输入的数字签名,但是程序限制我们无法直接对ADMIN_TOKEN签名,得到flag的条件就是伪造这个内容的数字签名。
将ADMIN_TOKEN表示为M,我们随机取一个小数r,此处让r=2.
构造 M ′ = ( r e ∗ M )   m o d   ( N ) M^{'}=(r^e*M)\ mod\ (N) M=(reM) mod (N)
此时借助程序求出 M ′ M^{'} M的数字签名
S ′ = ( r e ∗ d ∗ M d )   m o d   ( N ) S^{'}=(r^{e*d}*M^d)\ mod \ (N) S=(redMd) mod (N)
我们需要伪造的数字签名是 S = M d   m o d ( N ) S=M^d \ mod (N) S=Md mod(N)
此时,我们发现 S = S ′ / r S=S^{'}/r S=S/r,构造完毕,进行验证就能拿到flag

具体操作

构造M’

import binascii
a=459922107199558918501733 #ADMIN_TOKEN = b"admin=True" 转化成10进制
n=0x954e1412ba207b8a246ea515e81425aeb5471cf5062b6497b2c76312ccf150498779ca540464b09fe573df68b0cfdcac124ba799b8546b45b49eaae9fadd630d1b5562a9993c6a3da72d5222e24aa6e1f9c663bfd07f31f0cdef87a54f2fbf7151afc3fd329bd16692dcfa6794c3d94d00fb2e11b49557a491be3e510f0c3e22163487df65e54d68f43a3ecea44e48dc929f2d321c6bfdb2c6c233c704e0618041ace0be91f637f423e6161b36a1fe0f04445ee1f48dc5960659706bbcb97c1667c5f17d0f2395dad348a88f3efb7fa06f99f7963749679eb697cd178fce6f65cfee5b6c9c36096c96f5b5532a6a3b44127afe27f10015dd71a644d455f800d5
e=65537
r=2
m=a*(r**e)%n
print(hex(m)) #构造出的M'

#0x48322bafd8204fbfe36bd1553187d93379f85d562ea0222a1da0a5956b9e4bd48c5d7d56c433b16b5d9c33ee6e5d308254c275745b1c45c5d1b2be359e578352e04945d5d678dfa51af6ba7e4b5002400c999347413186b2bc4b70007a5a0a1750d4ed5a6bf0ba5bb8b4c9a0026aa12feddc95a9930b9259cccc12717ddef6b5d8dad08ea5f7145f646449848cc63c6383bdeb2f45bd7d7d20fc1af4dac53d7e17a45c130b0a8ec1220b708c8dd453a1e5e6bbf23fffcadc2edc801b5bbce481350ec8bac14dfcf6236d2f0ee855c7e79d9411c57680e75c6996f205ea9a99e2e6d132b01d620e83363a1741a5b65853df03e2b106dbc1d6e7ad4809ca717ffd

输入程序,得到构造的数字签名
在这里插入图片描述根据构造的数字签名,求解需要的数字签名

import gmpy2
s=0x6d65dcfe8f09ae022186b63b2665f4457d710a80dd1b01fe52d064af2461f8f848d81a59c48905b156a7ffc6a92ec43a94c3f18ef3e28b34fea35b1ab3454d20927731c238505529f5f00a345c02215f144f8c47467e9053255edf8a995264817f37a8cd1a6e48d94587a53c72028ce0fe025bc720b8a64ab0dc818f7dbe2bbc12b6e22cc150539f2496ab6b9de2f4cf41db2f6db4f5f3a031954fa7d83a8cffbcf2866f8cd85736f8a2c60c8778cd260beb597235d1c20094fbf321c23de11e7963fbaf5265c35d6247811f9826733ced0f7406dafea90300a1e37c188188d40b6c6b25e33e41d34b2cfc013b28ea5213db4f20bbb0cbb113d4eb054e8e630e
e=65537
n=0x954e1412ba207b8a246ea515e81425aeb5471cf5062b6497b2c76312ccf150498779ca540464b09fe573df68b0cfdcac124ba799b8546b45b49eaae9fadd630d1b5562a9993c6a3da72d5222e24aa6e1f9c663bfd07f31f0cdef87a54f2fbf7151afc3fd329bd16692dcfa6794c3d94d00fb2e11b49557a491be3e510f0c3e22163487df65e54d68f43a3ecea44e48dc929f2d321c6bfdb2c6c233c704e0618041ace0be91f637f423e6161b36a1fe0f04445ee1f48dc5960659706bbcb97c1667c5f17d0f2395dad348a88f3efb7fa06f99f7963749679eb697cd178fce6f65cfee5b6c9c36096c96f5b5532a6a3b44127afe27f10015dd71a644d455f800d5
print(hex(((s)/(2))%n))

#0x36b2ee7f4784d70110c35b1d9332fa22beb885406e8d80ff296832579230fc7c246c0d2ce24482d8ab53ffe35497621d4a61f8c779f1459a7f51ad8d59a2a690493b98e11c282a94faf8051a2e0110af8a27c623a33f482992af6fc54ca93240bf9bd4668d37246ca2c3d29e390146707f012de3905c5325586e40c7bedf15de095b711660a829cf924b55b5cef17a67a0ed97b6da7af9d018caa7d3ec1d467fde794337c66c2b9b7c51630643bc669305f5acb91ae8e1004a7df990e11ef08f3cb1fdd7a932e1aeb123c08fcc13399e7687ba036d7f54818050f1be0c40c46a05b63592f19f20e9a5967e009d94752909eda7905dd865d889ea7582a7473187

将求解出的数字签名输入程序得到最终flag

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值