2020 CISCN Crypto lockrise

题解

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
import random
import os
from Crypto.Cipher import DES

'''
sbox=list(range(256))
random.shuffle(sbox)
print(sbox)
'''
sbox = [217, 25, 248, 51, 6, 37, 32, 69, 96, 117, 86, 108, 155, 50, 27, 249, 171, 82, 168, 245, 228, 195, 118, 187, 12, 109, 99, 241,
26, 41, 194, 205, 236, 185, 73, 35, 139, 175, 44, 116, 48, 148, 22, 142, 190, 114, 201, 60, 59, 89, 181, 13, 10, 197, 151, 219, 87, 198, 191, 93, 152, 230, 34, 124, 173, 146, 226, 40, 101, 165, 83, 212, 206, 229, 16, 95, 56, 107, 144, 250, 149, 153, 208, 133, 145, 156, 172, 162, 113, 100, 183, 127, 57, 223, 130, 72, 135, 84, 147, 15, 242, 177, 42, 23, 122, 54, 0, 131, 166, 244,
88, 231, 94, 235, 29, 125, 7, 232, 110, 90, 179, 75, 220, 71, 251, 45, 243, 207, 58, 120, 184, 9, 39, 218, 63, 38, 254, 167, 140, 53, 213, 214, 80, 85, 128, 8, 64, 174, 132, 233, 65, 200, 36, 115, 215, 192, 74, 203, 11, 134, 104, 170, 160, 227, 169, 246, 141, 221, 52, 21, 20, 47, 199, 33, 216, 182, 188, 143, 138, 102, 202, 105, 79, 49, 253, 30, 121, 103, 137, 1, 211, 150, 5, 55, 196, 247, 240, 178, 159, 24, 81, 224, 210, 67, 157, 91, 28, 18, 186, 126, 237, 98, 252, 2, 239, 43, 180, 209, 238, 225, 68, 119, 66, 46, 61, 17, 31, 112, 62, 158, 189, 234, 193, 111, 204, 19, 77, 222, 164, 14, 97, 3, 70, 255, 78, 129, 163, 92, 76, 4, 123, 176, 106, 161, 154, 136]

def lock(m):
r=[]
for i in m:
r.append(sbox[i])
return r

def peak(m):
r=m[-1:]+m[0:-1]
return r

def rise(m,k):
assert len(m)==len(k)
r=[]
for i in range(len(m)):
r.append(m[i]^k[i])
return r

key=os.urandom(8)

secret=[1,2,3,4,5,6,7,8]
r=lock(secret)
#[25, 248, 51, 6, 37, 32, 69, 96]
r=peak(r)
#[96, 25, 248, 51, 6, 37, 32, 69]
r=rise(r,key)

r=lock(r)
r=peak(r)
r=rise(r,key)

print("lockrise:",r)
print("k0 ^ k7:",key[0]^key[-1])

secret=os.urandom(8)
r=lock(secret)
r=peak(r)
r=rise(r,key)

r=lock(r)
r=peak(r)
r=rise(r,key)
print("encrypted:",r)
d=DES.new(secret,DES.MODE_ECB)
flag=b"flagxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
print(d.encrypt(flag).hex())

​ 拿到题目看有flag的地方判断是DES加密(ECB模式)

​ 所以想拿到flag,需要进行解密。对称加密,密文已知,则需要知道密钥secret,就能解出flag。

​ 分析一下题目的函数

  • lock(m): 取s-box[i], i属于m

  • peak(m): 对m进行循环右移

  • rise(m,key): 对m,key进行异或操作,m[i]^key[i]

    看一下可以利用的信息,关键点k0 ^ k7 = 160, 有256种可能

    同时加密过程

    r[6]=secret[6] -> sbox[r[6]] -> r[7] -> r[7] ^ k[7] -> sbox[r[7] ^ k[7] -> r[0] ->r[0] ^ k[0] -> r[0] ->lockrise[0]

1
2
3
4
5
for k7 in range(256):
k0 = 160 ^ k7
if sbox[r[7] ^ k7] ^ k0 == lockrise[0]:
print(k0, k7)
# 0 160

所以k[0]和k[7]的值分别为0 160

因为

1
sbox[r[i] ^ key[i]] ^ key[i+1] == lockrise[i + 1]

知道r[0]可以循环求解

1
2
3
4
5
6
7
8
9
key = [0]
for i in range(0, 7):
for k in range(256):
if sbox[r[i] ^ key[i]] ^ k == lockrise[i + 1]:
print(i, k)
key.append(k)
break
print(key)
# [0, 180, 224, 60, 139, 193, 154, 160]

再根据第二次的r和key反过来求解secret,将所有函数和次序反过来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def inv_rise(m, k):
assert len(m) == len(k)
r = []
for i in range(len(m)):
r.append(m[i] ^ k[i])
return r

def inv_peak(m):
r = m[1:] + m[0:1] # left shift
return r

def inv_lock(m):
r = []
for i in m:
r.append(sbox.index(i))
return r
1
2
3
4
5
6
7
8
9
encrypted = [32, 98, 40, 152, 125, 149, 87, 167]
x = inv_rise(encrypted, key)
x = inv_peak(x)
x = inv_lock(x)
x = inv_rise(x, key)
x = inv_peak(x)
x = inv_lock(x)
print(x)
# [35, 239, 81, 231, 237, 218, 108, 166]

得到secret的值为[35, 239, 81, 231, 237, 218, 108, 166]

1
2
3
4
5
6
7
from Crypto.Cipher import DES
secret = [35, 239, 81, 231, 237, 218, 108, 166]
flag = bytes.fromhex("0304eb66ffd8a1e1ee60b7e923c7823da10bb23fba254ab6748137b204133e2a35759572068c3a0c")

d = DES.new(bytes(secret), DES.MODE_ECB)
print(d.decrypt(flag))
# b'flag{lock_peak_rise_repeat_2333_7481233}'

得到flag