发布于 

差分攻击Grain论文复现

早年的题目了,带新人的时候才想起没写wp

直接上题目源码

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
import random
import string
import hashlib
import sys
from collections import deque
import sys
#flag="flag{xxxxxxxx}"
count=0
assert(guess<160)

class generator:
def __init__(self, key: list, iv: list, hint: bool, k=0, m=0):
self.NFSR = deque()
self.LFSR = deque()

for i in range(80):
self.NFSR.append(key[i])

for i in range(64):
self.LFSR.append(iv[i])

for i in range(64, 80):
self.LFSR.append(1)

self.clock()

if hint:
s = self.NFSR + self.LFSR
for i in range(k, k + m):
s[i] ^= 1
self.NFSR = deque(list(s)[:80])
self.LFSR = deque(list(s)[80:])

def clock(self):
for i in range(160):
zi = self.PRGA()
self.NFSR[79] ^= zi
self.LFSR[79] ^= zi

def PRGA(self):
x0 = self.LFSR[3]
x1 = self.LFSR[25]
x2 = self.LFSR[46]
x3 = self.LFSR[64]
x4 = self.NFSR[63]

hx = x1 ^ x4 ^ (x0 & x3) ^ (x2 & x3) ^ (x3 & x4) ^ (x0 & x1 & x2) ^ (x0 & x2 & x3) \
^ (x0 & x2 & x4) ^ (x1 & x2 & x4) ^ (x2 & x3 & x4)

zi = (self.NFSR[1] ^ self.NFSR[2] ^ self.NFSR[4] ^ self.NFSR[10] ^ self.NFSR[31] ^ self.NFSR[43] ^ self.NFSR[
56]) ^ hx

fx = self.LFSR[62] ^ self.LFSR[51] ^ self.LFSR[38] ^ self.LFSR[23] ^ self.LFSR[13] ^ self.LFSR[0]

gx = self.LFSR[0] ^ self.NFSR[62] ^ self.NFSR[60] ^ self.NFSR[52] ^ self.NFSR[45] ^ self.NFSR[37] \
^ self.NFSR[33] ^ self.NFSR[28] ^ self.NFSR[21] ^ self.NFSR[14] ^ self.NFSR[9] ^ self.NFSR[0] \
^ (self.NFSR[63] & self.NFSR[60]) ^ (self.NFSR[37] & self.NFSR[33]) ^ (self.NFSR[15] & self.NFSR[9]) \
^ (self.NFSR[60] & self.NFSR[52] & self.NFSR[45]) ^ (self.NFSR[33] & self.NFSR[28] & self.NFSR[21]) \
^ (self.NFSR[63] & self.NFSR[45] & self.NFSR[28] & self.NFSR[9]) ^ (
self.NFSR[60] & self.NFSR[52] & self.NFSR[37] & self.NFSR[33]) \
^ (self.NFSR[63] & self.NFSR[60] & self.NFSR[21] & self.NFSR[15]) ^ (
self.NFSR[63] & self.NFSR[60] & self.NFSR[52] & self.NFSR[45] & self.NFSR[37]) \
^ (self.NFSR[33] & self.NFSR[28] & self.NFSR[21] & self.NFSR[15] & self.NFSR[9]) ^ (
self.NFSR[52] & self.NFSR[45] & self.NFSR[37] & self.NFSR[33] & self.NFSR[28] & self.NFSR[21])

self.LFSR.popleft()
self.LFSR.append(fx)
self.NFSR.popleft()
self.NFSR.append(gx)

return zi

for round in range(len(glist)):
guess = glist[round]
k = guess // 2
m = guess % 10
if m == 0:
m = 10
key = bin(random.getrandbits(80))[2:].zfill(80)
key = list(map(int, key))
iv = bin(random.getrandbits(64))[2:].zfill(64)
iv = list(map(int, iv))
a = generator(key, iv, False)
k1 = []
for i in range(160):
k1.append(a.PRGA())
k1 = int("".join(list(map(str, k1))), 2)
b = generator(key, iv, True, k, m)
k2 = []
for i in range(160):
k2.append(b.PRGA())
k2 = int("".join(list(map(str, k2))), 2)
print(f"round {round+1}")
print("Here are some tips might help your:")
print(k1)
print(k2)
num = int(input(">"))
if num == guess:
count += 1
print("you are smart!\n")
else:
print("wrong!\n")
print(guess)

if count == 32:
print(flag)
sys.exit(0)
else:
print("you lose the game, bye!")
sys.exit(0)

可以看出,题目是给了一段中间状态的错误,目的是通过密文获取错误信息。

很难不想到是差分。

然后我们先识别算法,通过key和iv长度+NFSR这些信息可以得到算法为Grain。

查找Grain+差分故障得到论文 Multi-Bit Differential Fault Analysis of Grain-v1.pdf ,然后复现文中算法即可。

上exp:

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
t=[(x//2,1+((x-1)%10)) for x in range(160)]

def makelist():
d={}
l=None
ln=0
for c in t:
n={}
k=c[0]
m=c[1]
print(c)
for i in range(2**12):
key = bin(random.getrandbits(80))[2:].zfill(80)
key = list(map(int, key))
iv = bin(random.getrandbits(64))[2:].zfill(64)
iv = list(map(int, iv))
a = generator(key, iv, False)
k1 = []
for i in range(30):
k1.append(a.PRGA())
k1 = int("".join(list(map(str, k1))), 2)
b = generator(key, iv, True, k, m)
k2 = []
for i in range(30):
k2.append(b.PRGA())
k2 = int("".join(list(map(str, k2))), 2)
z=k1^k2
z=bin(z)[2:30]
if z not in n:
n[z]=1
else:
n[z]+=1
d[c]=n
print(d)
return d



a1=1162564649569280272824832673863340173613940617997
a2=1143295317999501070882408868365435263773441633504

try:
f=open("DC.txt","r")
s=f.read()
if len(s)<1:
raise(Exception)
except :
f=open("DC.txt","w")
d=makelist()
f.write(str(d))
else :
d=eval(s)

f.close()


def check2(a,b):
H=bin((a^b)>>130)[2:30]
l=None
ln=0
for c in t:
if H in d[c]:
p=d[c]
if p[H]>ln:
ln=p[H]
l=c
print(l)
return l



while 1:
check2(a1,a2)
print("next")
a1=int(input())
a2=int(input())



需要人工手动运行。


本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 [@Zuni](http://example.com/) 创建,使用 Stellar 作为主题。