日常鼓励自己:没人会嘲笑竭尽全力的人。
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′=(re∗M) mod (N)
此时借助程序求出
M
′
M^{'}
M′的数字签名
S
′
=
(
r
e
∗
d
∗
M
d
)
m
o
d
(
N
)
S^{'}=(r^{e*d}*M^d)\ mod \ (N)
S′=(re∗d∗Md) 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