XiangYunCupWP

huangx607087 祥云杯密码题wp

0. 简介

前几天打了一下祥云杯的密码题,4道题目,在别人指指点点下,写了三道题,这几天完善一下自己的wp

1.Guess

拿到题目后,先审计一下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#task.py
from Crypto.Util.number import (
bytes_to_long,
getPrime,
long_to_bytes,
getRandomNBitInteger,
)
import random
import hashlib
from math import gcd
import socketserver
KEYSIZE = 512
WELCOME = "welcome to my funny challenge !!! Can you guess right 32 times in a row? "
String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz"
def exgcd(a, b):
if b == 0:
return 1, 0, a
else:
x, y, q = exgcd(b, a % b)
x, y = y, (x - (a // b) * y)
return x, y, q
def invert(a,p):
x, y, q = exgcd(a,p)
if q != 1:
raise Exception("No solution.")
else:
return (x + p) % p
def lcm(a,b):
return a*b // gcd(a,b)
def proof_of_work():
STR = "".join([String[random.randint(0, len(String) - 1)] for _ in range(16)])
HASH = hashlib.sha256(STR.encode()).hexdigest()
return STR[:4], STR[4:], HASH
def keygen():
# part 1
p, q = getPrime(KEYSIZE), getPrime(KEYSIZE)
n = p * q
g = n + 1
LAMBDA = lcm(p - 1, q - 1)
# part 2
_key = open("key", "r").read()
key = []
for i in _key.split("\n"):
for j in i[1:-1].split(" "):
if int(j) not in key:
key.append(int(j))
assert len(key) == 80
assert key[0] == 119 and key[1] == 241 and key[2] == 718 and key[3] == 647
return n, g, LAMBDA, key
def enc(n, g, m):
while 1:
r = random.randint(2, n - 1)
if gcd(r, n) == 1:
break
c = (pow(g, m, n ** 2) * pow(r, n, n ** 2)) % (n ** 2)
return c
def dec(n, g, LAMBDA, c):
L1 = (pow(c, LAMBDA, n ** 2) - 1) // n
L2 = (pow(g, LAMBDA, n ** 2) - 1) // n
m = (invert(L2, n) * L1) % n
return m
class server(socketserver.BaseRequestHandler):
def _recv(self):
data = self.request.recv(1024)
return data.strip()
def _send(self, msg, newline=True):
if isinstance(msg, bytes):
msg += b"\n"
else:
msg += "\n"
msg = msg.encode()
self.request.sendall(msg)
def handle(self):
print("Service start.")
START, END, HASH = proof_of_work()
self._send("SHA-256(?+{}) == {}".format(END, HASH))
RCV = self._recv().decode()
if RCV != START:
return
flag = open("flag", "rb").read()
self._send(WELCOME)
# step 1. KeyGen
for _ in range(32):
self._send("round " + str(_+1))
n, g, LAM, KEY = keygen()
self._send("Step 1 - KeyGen. This is my public key.")
self._send("n = " + str(n))
self._send("g = " + str(g))
# step 2. Phase 1
self._send(
"Step 2 - Phase 1. Now, you can give me one ciphertexts,I will return the corresponding plaintext."
)
self._send("Please give me one decimal ciphertext.")
cipher = int(self._recv().decode())
plaintext = str(dec(n, g, LAM, cipher))
self._send("This is the corresponding plaintext.")
self._send(plaintext)

# step 3. challenge
self._send(
"Step 3 - Challenge. Now, you must give me two decimal plaintexts(m0,m1), I will encry them and return a ciphertext randomly"
)
self._send("Give me m0.")
plaintext1 = int(self._recv().decode())
self._send("Give me m1.")
plaintext2 = int(self._recv().decode())

if (
plaintext1 <= 2
or plaintext2 <= 2
or len(bin(plaintext1)) != len(bin(plaintext2))
):
return
R = 2 * random.randint(0, 39)
I = random.randint(0, 1)
cipher1 = enc(n, g, plaintext1 * plaintext2 * KEY[R])
cipher2 = enc(n, g, plaintext1 * plaintext2 * KEY[R + 1])
self._send("This is a ciphertext.")
self._send(str([cipher1, cipher2][I]))
# step 4. Phase 2
self._send(
"Step 4 - Phase 2. Now, you can give me some ciphertexts,I will return the corresponding plaintext.But you can not give me the ciphertext that I give you in step 3."
)
self._send("Please give me one decimal ciphertext ")
cipher = int(self._recv().decode())
plaintext = str(dec(n, g, LAM, cipher))
if int(plaintext) == plaintext1 * plaintext2 * KEY[R] or int(plaintext) == plaintext1 * plaintext2 * KEY[R+1]:
return
self._send("This is the corresponding plaintext.")
self._send(plaintext)
# step.5 Guess
self._send(
"Step 5 - Guess. You must tell me which ciphertext was I give you in step 3, 0 or 1(m0 -> c0 , m1 -> c1)?"
)
Guess = int(self._recv().decode())
if Guess == I:
self._send("Good! You are right")
else:
self._send("Sorry!")
return
self._send(flag)
class ForkedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 10001
server = ForkedServer((HOST, PORT), server)
server.allow_reuse_address = True
server.serve_forever()

然后题目还给出了一个key的加密方法,并给出了hint文件用于求key。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from Crypto.Util.number import getRandomNBitInteger
while 1:
A = []
key = random_matrix(ZZ, 20, 4, x = 100, y =1000)
for i in range(20):
for j in range(4):
if key[i,j] not in A:
A.append(key[i,j])
if len(A) == 80:
break
hint = Matrix(key * vector([getRandomNBitInteger(1024) for _ in range(4)]) for _ in range(12))
Matrix(M* vector([randint(1,5) for _ in range(4)]) for _ in range(12))
open('key','w').write(str(key))
open('hint','w').write(str(hint))

key = random_matrix(ZZ, 20, 4, x = 100, y =1000)这个代码表示在整数定义域内生成一个$20$行$4$列,定义域为整数的矩阵,其中矩阵中最小数字不小于$100$,最大数字不超过$1000$。然后又注意到hint又是一个key*vector的矩阵,其中vector中的所有数字都是$1024$个比特。

因此,通过这个key的加密方法我们可以看出:由于这里是右乘向量,因此这边所有的向量都是列向量。所以我们可以理解成一个$20$行$4$列的矩阵,乘上一个$4$行$12$列的矩阵,得到一个$20$行$12$列的矩阵。而最后的hint是$12$行$20$列。因此我们读入数据后,需要转置一下。

看到矩阵、又看到了非常小的数字(几百)和非常大的数字($O(2^{1024})$级别的数字),因此很显然这里需要上一下LLL——问题是怎么上这个LLL还是个问题。

我们这就来简单地说一下这个是怎么做的。

由于小数与大数的线性组合,我们可以得到
$$
\sum_{i=1}^{20} a_ix_i=S_H
$$
因此,$(a_1,a_2,a_3,a_4,…,a_{20},0)$也是一个小向量,并且在数据规模相差巨大的情况下——可以认为这个是最短向量。

所以我们可以对读入后的$M$矩阵先进行随意打乱,然后随即调整LLL时的参数就可以得到题目中给出的四组解了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from random import *
def check(L):
for i in L:
if i not in range(100,1001):
return 0
return 1
f=open("hint.txt","r")
D=f.readlines()
Numbers=[]
for i in D:
dataln=i[1:-2].split(" ")
for j in dataln:
Numbers.append(int(j))
M=[]
for i in range(0,len(Numbers),20):
M.append(Numbers[i:i+20])
Lns=[]
while len(Lns)<4:
shuffle(M)
Mlll=matrix(12,20,M).LLL(delta=float(randint(25000, 99999)/100000))
for dataln in Mlll:
if dataln[0]<0:
dataln=-dataln
if dataln not in Lns and check(dataln):
print(len(Lns),dataln)
Lns.append(dataln)
"""
Output:
0 (241, 232, 548, 400, 186, 333, 646, 727, 286, 877, 810, 121, 237, 745, 201, 542, 244, 396, 158, 641)
1 (119, 521, 142, 637, 614, 746, 299, 416, 638, 288, 995, 498, 639, 585, 114, 885, 558, 783, 899, 751)
2 (718, 550, 349, 939, 148, 355, 942, 685, 313, 577, 184, 130, 307, 983, 611, 903, 271, 530, 566, 427)
3 (647, 918, 613, 936, 461, 281, 977, 888, 128, 653, 309, 780, 526, 216, 944, 123, 430, 860, 113, 129)
"""

解出所有的key之后,我们就可以根据题目assert的内容,重新调整key中所有数字的内容,这是最终调整出来的真正的key数组:

1
key=[119, 241, 718, 647, 521, 232, 550, 918, 142, 548, 349, 613, 637, 400, 939, 936, 614, 186, 148, 461, 746, 333, 355, 281, 299, 646, 942, 977, 416, 727, 685, 888, 638, 286, 313, 128, 288, 877, 577, 653, 995, 810, 184, 309, 498, 121, 130, 780, 639, 237, 307, 526, 585, 745, 983, 216, 114, 201, 611, 944, 885, 542, 903, 123, 558, 244, 271, 430, 783, 396, 530, 860, 899, 158, 566, 113, 751, 641, 427, 129]

解出这个key之后,我们就得到了里面所有的内容,然后看到题目中的代码是Paillier同态加密算法,这个算法有个特点就是它具有同态性。因为它的加密表达式为:
$$
c\equiv g^{m}r^{n} \pmod {n^{2}}
$$
其中$g,r$均为与$n$互质的随机数 ,是加密前已经确定好的内容了。因此我们如果已知$c_1$是$m_1$的加密结果,$c_2$是$m_2$的加密结果,那么$m_1+m_2$的加密的结果就是$c_1c_2$。

所以利用这一性质,我们只需要每次发送一个$m_{99}$,将$c$接收后发送个$c^2$过去,然后除以$2m_{99}^2$,判断一下最后解密出的值在key数组中下标的奇偶性就行了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
from pwn import *
from random import *
from Crypto.Util.number import *
from KEY3 import key
from hashlib import sha256
def getyzm(s12,s64):
s12,s64=s12.decode(),s64.decode()
Table="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
for i in Table:
for j in Table:
for k in Table:
for l in Table:
s4=i+j+k+l
s16=s4+s12
if(sha256(s16.encode()).hexdigest()==s64):
return s4
def recpas(sh,T=1):
for i in range(T):
s=sh.recvline()
return s
#----------MAIN BELOW----------#
sh=remote("47.104.85.225",57811)
s1=sh.recvline(keepends=False)
print(s1)
sh.sendline(getyzm(s1[10:22],s1[27:91]))
for i in range(32):
m99=randint(3,9001)
print(f"Round {i+1}/32 Begins with using m99={m99}")
sh.recvuntil(b"n = ")
n=int(sh.recvline(keepends=False))
sh.recvuntil(b"g = ")
g=int(sh.recvline(keepends=False))
recpas(sh,2)
sh.send(f"{m99}\n")
c99=int(recpas(sh,2))
#print(m99,c99)
recpas(sh,2)
sh.send(f"{m99}\n")
recpas(sh)
sh.send(f"{m99}\n")
c=int(recpas(sh,2))
#print(c)
recpas(sh,2)
sh.send(f"{pow(c,2,n**2)}\n")
m=int(recpas(sh,2))
#print(f"{m}")
recpas(sh)
sh.send(f"{key.index(m//(2*m99**2))%2}\n")
print(recpas(sh))
sh.interactive()
#flag{e87fdfb6-8007-4e1c-861f-5bde3c8badb3}

2.myRSA

题目代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# myRSA
from Crypto.Util.number import getPrime,bytes_to_long as b2l
from math import gcd
import hashlib
import random
import socketserver
KEYSIZE = 512
alpha = 2.0314159265358979
WELCOME = 'Welcome to use my better RSA!!!!!!So, what do you want now?'
menu = '1. encry \n2. getflag\n3. exit'
String = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz'
def proof_of_work():
STR = ''.join([String[random.randint(0,len(String)-1)] for _ in range(16) ])
HASH = hashlib.sha256(STR.encode()).hexdigest()
return STR[:4],STR[4:],HASH
def key_gen():
while True:
p,q = getPrime(KEYSIZE),getPrime(KEYSIZE)
e = 0x10001
if gcd(e,(p-1)*(q-1)):
break
key = [getPrime(int(KEYSIZE*alpha)) for _ in range(128)]
return (p,q,e),key
# encrypto
def encry(message,key,p,q,e):
k1,k2 = key[random.randint(0,127)],key[random.randint(0,127)]
x = p**2 * (p + 3*q - 1 ) + q**2 * (q + 3*p - 1)
y = 2*p*q + p + q
z = k1 + k2
c = pow(b2l(message),e,p*q)
return x * c + y * c + z
# get flag
def getflag(flag,key,p,q,e):
return encry(flag,key,p,q,e)
class server(socketserver.BaseRequestHandler):
def _recv(self):
data = self.request.recv(1024)
return data.strip()
def _send(self, msg, newline=True):
if isinstance(msg , bytes):
msg += b'\n'
else:
msg += '\n'
msg = msg.encode()
self.request.sendall(msg)
def handle(self):
START,END,HASH = proof_of_work()
self._send('SHA-256(?+{}) == {}'.format(END,HASH))
RCV = self._recv().decode()
if RCV != START:
return
self._send("I'm a CryptoRookie,so my Crypto system take time, please wait a minute XD!")
(p,q,e),key = key_gen()
flag = open('flag','rb').read()
self._send(WELCOME)
self._send('This is my public key:\nn = {}\ne = {}'.format(str(p*q),str(e)))
for _ in range(16):
self._send(menu)
COI = int(self._recv().decode())
if COI == 1 :
self._send('Give me your message')
message = self._recv()
self._send('Your encry message:')
self._send(str(encry(message,key,p,q,e)))
elif COI == 2:
self._send('This is your favourite:\n')
self._send(str(encry(flag,key,p,q,e)))
elif COI == 3:
self._send('Bye~')
break
class ForkedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
if __name__ == "__main__":
HOST, PORT = '0.0.0.0', 10001
server = ForkedServer((HOST, PORT), server)
server.allow_reuse_address = True
server.serve_forever()

先确定一下这些数字的大小:$p,q$都是$512$位,key数组中的所有数字都是$1040$位。$x=p^2 (p + 3q - 1 ) + q^2 (q + 3p - 1)$,数量级大概是$1500$多位,$y=2pq + p + q$,数量级大约是$1030$位。

所以$x+y=(p+q)^3-(p+q)^2+(p+q)-4pq$。而$(p+q-1)^3=(p+q)^3-3(p+q)^2+3(p+q)-1$,两者的值非常接近。

所以可以认为$\sqrt[3]{x+y}=p+q-1$。然后对flag的值除以$(x+y)$即可。而$\dfrac{\ln z}{\ln 2}=129$,因此$z$的值可以直接忽略。

3.RandomRSA

题目就是通过设置random的seed的方法,通过不断生成随机数,每一轮计算一个特定的随机数与str(dp)进行异或的值。

基本没什么难的内容,直接逆回去就行了,然后直接套已知dp的脚本,不过要用python2.7。

chall.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from Crypto.Util.number import *
import gmpy2
import libnum
import random
import binascii
import os
flag=r'flag{}'
p=getPrime(512)
q=getPrime(512)
e=0x10001
n=p*q
ct=pow(flag,e,n)
print("n="+ n)
print("ct="+ ct)
dp=r''
seeds = []
for i in range(0,len(dp)):
seeds.append(random.randint(0,10000))
res = []
for i in range(0, len(dp)):
random.seed(seeds[i])
rands = []
for j in range(0,4):
rands.append(random.randint(0,255))

res.append(ord(dp[i]) ^ rands[i%4])
del rands[i%4]
print(str(rands))
print(res)
print(seeds)
# n=81196282992606113591233615204680597645208562279327854026981376917977843644855180528227037752692498558370026353244981467900057157997462760732019372185955846507977456657760125682125104309241802108853618468491463326268016450119817181368743376919334016359137566652069490881871670703767378496685419790016705210391
# ct=61505256223993349534474550877787675500827332878941621261477860880689799960938202020614342208518869582019307850789493701589309453566095881294166336673487909221860641809622524813959284722285069755310890972255545436989082654705098907006694780949725756312169019688455553997031840488852954588581160550377081811151
# [58, 53, 122] [145, 124, 244] [5, 19, 192] [255, 23, 64] [57, 113, 194] [246, 205, 162] [112, 87, 95] [215, 147, 105] [16, 131, 38] [234, 36, 46] [68, 61, 146] [148, 61, 9] [139, 77, 32] [96, 56, 160] [121, 76, 17] [114, 246, 92] [178, 206, 60] [168, 147, 26] [168, 41, 68] [24, 93, 84] [175, 43, 88] [147, 97, 153] [42, 94, 45] [150, 103, 127] [68, 163, 62] [165, 37, 89] [219, 248, 59] [241, 182, 8] [140, 211, 146] [88, 226, 2] [48, 150, 56] [87, 109, 255] [227, 216, 65] [23, 190, 10] [5, 25, 64] [6, 12, 124] [53, 113, 124] [255, 192, 158] [61, 239, 5] [62, 108, 86] [123, 44, 64] [195, 192, 30] [30, 82, 95] [56, 178, 165] [68, 77, 239] [106, 247, 226] [17, 46, 114] [91, 71, 156] [157, 43, 182] [146, 6, 42] [148, 143, 161] [108, 33, 139] [139, 169, 157] [71, 140, 25] [28, 153, 26] [241, 221, 235] [28, 131, 141] [159, 111, 184] [47, 206, 11] [220, 152, 157] [41, 213, 97] [4, 220, 10] [77, 13, 248] [94, 140, 110] [25, 250, 226] [218, 102, 109] [189, 238, 66] [91, 18, 131] [23, 239, 190] [159, 33, 72] [183, 78, 208] [209, 213, 101] [111, 50, 220] [166, 104, 233] [170, 144, 10] [187, 87, 175] [195, 59, 104] [165, 179, 179] [99, 247, 153] [195, 61, 100] [223, 159, 165] [230, 93, 184] [87, 28, 35] [35, 122, 38] [158, 188, 163] [229, 192, 222] [12, 12, 192] [207, 95, 224] [127, 113, 137] [22, 114, 143] [13, 45, 144] [70, 140, 211] [57, 101, 42] [132, 62, 129] [40, 128, 124] [1, 132, 161] [164, 33, 133] [252, 201, 32] [8, 18, 247] [1, 88, 55] [201, 135, 186] [101, 254, 125] [236, 196, 39] [148, 24, 103] [101, 29, 253] [97, 156, 64] [90, 103, 91] [50, 48, 80] [206, 22, 93] [11, 114, 174] [61, 132, 247] [215, 32, 232] [95, 128, 90] [57, 35, 228] [163, 143, 107] [178, 250, 28] [64, 107, 225] [106, 115, 207] [85, 134, 21] [118, 201, 76] [234, 34, 22] [241, 236, 122] [111, 185, 127] [1, 26, 164] [254, 57, 117] [243, 27, 32] [161, 88, 80] [50, 165, 93] [87, 182, 216] [184, 159, 63] [167, 166, 123] [37, 78, 33] [186, 81, 58] [48, 3, 239] [70, 186, 13] [56, 108, 178] [54, 55, 235] [105, 180, 105] [16, 194, 98] [136, 11, 41] [18, 203, 79] [185, 114, 170] [148, 181, 223] [118, 57, 160] [23, 250, 181] [235, 219, 228] [44, 151, 38] [185, 224, 134] [42, 162, 122] [3, 9, 158] [129, 245, 2] [66, 241, 92] [80, 124, 36]
# [55, 5, 183, 192, 103, 32, 211, 116, 102, 120, 118, 54, 120, 145, 185, 254, 77, 144, 70, 54, 193, 73, 64, 0, 79, 244, 190, 23, 215, 187, 53, 176, 27, 138, 42, 89, 158, 254, 159, 133, 78, 11, 155, 163, 145, 248, 14, 179, 23, 226, 220, 201, 5, 71, 241, 195, 75, 191, 237, 108, 141, 141, 185, 76, 7, 113, 191, 48, 135, 139, 100, 83, 212, 242, 21, 143, 255, 164, 146, 119, 173, 255, 140, 193, 173, 2, 224, 205, 68, 10, 77, 180, 24, 23, 196, 205, 108, 28, 243, 80, 140, 4, 98, 76, 217, 70, 208, 202, 78, 177, 124, 10, 168, 165, 223, 105, 157, 152, 48, 152, 51, 133, 190, 202, 136, 204, 44, 33, 58, 4, 196, 219, 71, 150, 68, 162, 175, 218, 173, 19, 201, 100, 100, 85, 201, 24, 59, 186, 46, 130, 147, 219, 22, 81]
# [4827, 9522, 552, 880, 7467, 7742, 9425, 4803, 6146, 4366, 1126, 4707, 1138, 2367, 1081, 5577, 4592, 5897, 4565, 2012, 2700, 1331, 9638, 7741, 50, 824, 8321, 7411, 6145, 1271, 7637, 5481, 8474, 2085, 2421, 590, 7733, 9427, 3278, 5361, 1284, 2280, 7001, 8573, 5494, 7431, 2765, 827, 102, 1419, 6528, 735, 5653, 109, 4158, 5877, 5975, 1527, 3027, 9776, 5263, 5211, 1293, 5976, 7759, 3268, 1893, 6546, 4684, 419, 8334, 7621, 1649, 6840, 2975, 8605, 5714, 2709, 1109, 358, 2858, 6868, 2442, 8431, 8316, 5446, 9356, 2817, 2941, 3177, 7388, 4149, 4634, 4316, 5377, 4327, 1774, 6613, 5728, 1751, 8478, 3132, 4680, 3308, 9769, 8341, 1627, 3501, 1046, 2609, 7190, 5706, 3627, 8867, 2458, 607, 642, 5436, 6355, 6326, 1481, 9887, 205, 5511, 537, 8576, 6376, 3619, 6609, 8473, 2139, 3889, 1309, 9878, 2182, 8572, 9275, 5235, 6989, 6592, 4618, 7883, 5702, 3999, 925, 2419, 7838, 3073, 488, 21, 3280, 9915, 3672, 579]

6.py

1
2
3
4
5
6
7
8
9
10
from given import *import random
s=""
for i in range(len(res)):
random.seed(seeds[i])
arr=[]
for j in range(4):
arr.append(random.randint(0,255))
s+=chr(res[i]^arr[i%4])
print(s)#dp
#5372007426161196154405640504110736659190183194052966723076041266610893158678092845450232508793279585163304918807656946147575280063208168816457346755227057

1.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from gmpy2 import *

e = 65537
n = 81196282992606113591233615204680597645208562279327854026981376917977843644855180528227037752692498558370026353244981467900057157997462760732019372185955846507977456657760125682125104309241802108853618468491463326268016450119817181368743376919334016359137566652069490881871670703767378496685419790016705210391
c = 61505256223993349534474550877787675500827332878941621261477860880689799960938202020614342208518869582019307850789493701589309453566095881294166336673487909221860641809622524813959284722285069755310890972255545436989082654705098907006694780949725756312169019688455553997031840488852954588581160550377081811151
dp=5372007426161196154405640504110736659190183194052966723076041266610893158678092845450232508793279585163304918807656946147575280063208168816457346755227057
for x in range(1, e):
if(e*dp%x==1):
p=(e*dp-1)//x+1
if(n%p!=0):
continue
q=n//p
phin=(p-1)*(q-1)
d=invert(e, phin)
m=powmod(c, d, n)
if(len(hex(m)[2:])%2==1):
continue

print("m:",m)
#print(hex(m)[2:])
print("flag:",bytes.fromhex(hex(m)[2:]))
"""
Result:
m: 56006392793406549012915975207582000335336081517127286295437299100128144059518792192004013138662286717
flag: b'flag{74281db3-c6f0-e59a-4da6-39b8c71250fe}'
"""

4. 总结

这三道题还是有点难度的,祥云杯密码学是4道题目,还有一题不是很会做,等待着后期复现吧。。。

想不到大二就这么开始了,8月30日第一天上课,也在补我之前摸的鱼,有点累。


XiangYunCupWP
http://example.com/2021/08/30/XiangYunCupWP/
作者
huangx607087
发布于
2021年8月30日
许可协议