安询杯-Crypto题目复现Writeup
加油! -----2024-01-05 16:35:57
0x00 题目复现
下载完事之后复制源代码,打开pycharm直接运行
之后访问本地的127.0.0.1:10001,可以直接看见赛题。
0x01 Cry1
打开附件
# -*- coding:utf-8 -*-
import os
import random
import string
import hashlib
import socketserver
from Crypto.Util.number import isPrime, long_to_bytes, getStrongPrime, bytes_to_long
flag = b"D0g3{******************************************}"
class MyServer(socketserver.BaseRequestHandler):
def proof(self):
random.seed(os.urandom(8))
random_str = ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(20)])
str_sha256 = hashlib.sha256(random_str.encode()).hexdigest()
self.request.sendall(('SHA256(XXXX + %s):%s\n' % (random_str[4:], str_sha256)).encode())
self.request.sendall('Give Me XXXX:\n'.encode())
XXXX = self.request.recv(2048).strip()
if hashlib.sha256((XXXX + random_str[4:].encode())).hexdigest() != str_sha256:
return False
return True
def getPQN(self):
while True:
p = getStrongPrime(2048)
q = getStrongPrime(2048)
n = p * q
if p.bit_length() == 2048 and q.bit_length() == 2048 and n.bit_length() == 4096:
return p, q, n
def encrypt(self):
p, q, n = self.getPQN()
m = bytes_to_long(flag)
e = 0x10001
c = pow(m, e, n)
p = bin(p)[2:]
p1 = list(p[:1024])
p2 = list(p[1024:])
p1[random.choice([i for i, c in enumerate(p1) if c == '1'])] = '0'
p2[random.choice([i for i, c in enumerate(p1) if c == '0'])] = '1'
return n, ''.join(p1) + ''.join(p2), c
def handle(self):
if not self.proof():
self.request.sendall(b'Error Hash!')
return
n, p, c = self.encrypt()
self.request.sendall('Press 1 to get ciphertext\n'.encode())
number = self.request.recv(512).strip().decode()
if number == '1':
self.request.sendall((str(n) + '\n').encode())
self.request.sendall((str(p) + '\n').encode())
self.request.sendall((str(c) + '\n').encode())
else:
self.request.sendall('Incorrect input!\n'.encode())
return
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
if __name__ == '__main__':
sever = socketserver.ThreadingTCPServer(('0.0.0.0', 10001), MyServer)
ThreadedTCPServer.allow_reuse_address = True
ThreadedTCPServer.allow_reuse_port = True
sever.serve_forever()
我们来一点一点解析,首先看一下MyServer
random.seed(os.urandom(8)):
os.urandom(8): 这个函数调用使用操作系统的加密随机数生成器生成了8个随机字节。这些字节适合用作加密目的的安全种子。random.seed(): random.seed() 函数用于使用特定的种子值初始化Python中的随机数生成器。在您的代码中,您将由 os.urandom(8) 生成的字节作为种子传递
random_str = ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(20)])
这段代码的意思是从随机的在数字小写字母大写字母中取出20个字符,组成一个字符串。
str_sha256 = hashlib.sha256(random_str.encode()).hexdigest()
这段代码将随机字符串16进制后再进行sha256加密
self.request.sendall(('SHA256(XXXX + %s):%s\n' % (random_str[4:], str_sha256)).encode())
这段代码将一定内容发送出去
self.request.sendall('Give Me XXXX:\n'.encode())
XXXX = self.request.recv(2048).strip()
if hashlib.sha256((XXXX + random_str[4:].encode())).hexdigest() != str_sha256:
return False
这段很好理解,如果接受的数据满足前4位就返回True,要不然返回False。