Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
490 views
1
#
2
# Cryptography and Network Security, 5th ed
3
# by William Stallings
4
#
5
# SAGE Examples: Simplified DES
6
#
7
# Author: Dan Shumow, 2009
8
#
9
10
#
11
# The Expansions/Permutations are stored as lists of bit positions
12
#
13
14
P10_data = [3, 5, 2, 7, 4, 10, 1, 9, 8, 6];
15
16
P8_data = [6, 3, 7, 4, 8, 5, 10, 9];
17
18
LS1_data = [2, 3, 4, 5, 1];
19
20
LS2_data = [3, 4, 5, 1, 2];
21
22
IP_data = [2, 6, 3, 1, 4, 8, 5, 7];
23
24
IPinv_data = [4, 1, 3, 5, 7, 2, 8, 6];
25
26
EP_data = [4, 1, 2, 3, 2, 3, 4, 1];
27
28
P4_data = [2, 4, 3, 1];
29
30
SW_data = [5, 6, 7, 8, 1, 2, 3, 4];
31
32
#
33
# SDES lookup tables
34
#
35
36
S0_data = [[1, 0, 3, 2],
37
[3, 2, 1, 0],
38
[0, 2, 1, 3],
39
[3, 1, 3, 2]];
40
41
S1_data = [[0, 1, 2, 3],
42
[2, 0, 1, 3],
43
[3, 0, 1, 0],
44
[2, 1, 0, 3]];
45
46
def ApplyPermutation(X, permutation):
47
r"""
48
This function takes a permutation list (list of bit positions.)
49
And outputs a bit list with the bits taken from X.
50
"""
51
# permute the list X
52
l = len(permutation);
53
return [X[permutation[j]-1] for j in xrange(l)];
54
55
def ApplySBox(X, SBox):
56
r"""
57
This function Applies the SDES Sbox (by table look up
58
"""
59
r = 2*X[0] + X[3];
60
c = 2*X[1] + X[2];
61
o = SBox[r][c];
62
return [o & 2, o & 1];
63
64
#
65
# Each of these functions uses ApplyPermutation
66
# and a permutation list to perform an SDES
67
# Expansion/Permutation
68
#
69
70
def P10(X):
71
return ApplyPermutation(X, P10_data);
72
73
def P8(X):
74
return ApplyPermutation(X, P8_data);
75
76
def IP(X):
77
return ApplyPermutation(X, IP_data);
78
79
def IPinv(X):
80
return ApplyPermutation(X, IPinv_data);
81
82
def EP(X):
83
return ApplyPermutation(X, EP_data);
84
85
def P4(X):
86
return ApplyPermutation(X, P4_data);
87
88
def SW(X):
89
return ApplyPermutation(X, SW_data);
90
91
def LS1(X):
92
return ApplyPermutation(X, LS1_data);
93
94
def LS2(X):
95
return ApplyPermutation(X, LS2_data);
96
97
#
98
# These two functions peform the SBox substitutions
99
#
100
def S0(X):
101
return ApplySBox(X, S0_data);
102
103
def S1(X):
104
return ApplySBox(X, S1_data);
105
106
def concatenate(left, right):
107
r"""
108
Joins to bit lists together.
109
"""
110
ret = [left[j] for j in xrange(len(left))];
111
ret.extend(right);
112
return ret;
113
114
def LeftHalfBits(block):
115
r"""
116
Returns the left half bits from block.
117
"""
118
l = len(block);
119
return [block[j] for j in xrange(l/2)];
120
121
def RightHalfBits(block):
122
r"""
123
Returns the right half bits from block.
124
"""
125
l = len(block);
126
return [block[j] for j in xrange(l/2, l)];
127
128
def XorBlock(block1, block2):
129
r"""
130
Xors two blocks together.
131
"""
132
l = len(block1);
133
if (l != len(block2)):
134
raise ValueError, "XorBlock arguments must be same length"
135
return [(block1[j]+block2[j]) % 2 for j in xrange(l)];
136
137
def SDESKeySchedule(K):
138
r"""
139
Expands an SDES Key (bit list) into the two round keys.
140
"""
141
temp_K = P10(K);
142
143
left_temp_K = LeftHalfBits(temp_K);
144
right_temp_K = RightHalfBits(temp_K);
145
146
K1left = LS1(left_temp_K);
147
K1right = LS1(right_temp_K);
148
149
K1temp = concatenate(K1left, K1right);
150
K1 = P8(K1temp);
151
152
K2left = LS2(K1left);
153
K2right = LS2(K1right);
154
155
K2temp = concatenate(K2left, K2right);
156
157
K2 = P8(K2temp);
158
159
return (K1, K2);
160
161
def f_K(block, K):
162
r"""
163
Performs the f_K function supplied block and K.
164
"""
165
left_block = LeftHalfBits(block);
166
right_block = RightHalfBits(block);
167
168
temp_block1 = EP(right_block);
169
170
temp_block2 = XorBlock(temp_block1, K);
171
172
left_temp_block2 = LeftHalfBits(temp_block2);
173
right_temp_block2 = RightHalfBits(temp_block2);
174
175
S0_out = S0(left_temp_block2);
176
S1_out = S1(right_temp_block2);
177
178
temp_block3 = concatenate(S0_out, S1_out);
179
180
temp_block4 = P4(temp_block3)
181
182
temp_block5 = XorBlock(temp_block4, left_block);
183
184
output_block = concatenate(temp_block5, right_block)
185
186
return output_block;
187
188
def SDESEncrypt(plaintext_block, K):
189
r"""
190
Peforms a single SDES plaintext block encryption.
191
(Given plaintext and key as bit lists.)
192
"""
193
194
(K1, K2) = SDESKeySchedule(K);
195
print "K1:", K1
196
197
temp_block1 = IP(plaintext_block);
198
199
temp_block2 = f_K(temp_block1, K1);
200
201
print "After first steps:", (temp_block2)
202
203
temp_block3 = SW(temp_block2);
204
205
temp_block4 = f_K(temp_block3, K2);
206
207
output_block = IPinv(temp_block4);
208
209
return output_block;
210
211
def SDESDecrypt(ciphertext_block, K):
212
r"""
213
Performs a single SDES ciphertext block decryption.
214
(Given ciphertext and key as bit lists.)
215
"""
216
217
(K1, K2) = SDESKeySchedule(K);
218
219
temp_block1 = IP(ciphertext_block);
220
221
temp_block2 = f_K(temp_block1, K2);
222
223
temp_block3 = SW(temp_block2);
224
225
temp_block4 = f_K(temp_block3, K1);
226
227
output_block = IPinv(temp_block4);
228
229
return output_block;
230
231
def Reverse_First_Round_Encrypt(temp_block, K1):
232
233
temp_block5 = LeftHalfBits(temp_block);
234
right_block = RightHalfBits(temp_block);
235
236
#Use K1 and right_block to get left_block
237
temp_block1 = EP(right_block);
238
239
temp_block2 = XorBlock(temp_block1, K1);
240
241
left_temp_block2 = LeftHalfBits(temp_block2);
242
right_temp_block2 = RightHalfBits(temp_block2);
243
244
S0_out = S0(left_temp_block2);
245
S1_out = S1(right_temp_block2);
246
247
temp_block3 = concatenate(S0_out, S1_out);
248
249
temp_block4 = P4(temp_block3)
250
251
#To find left_block use XOR
252
left_block = XorBlock(temp_block4, temp_block5);
253
254
block = concatenate(left_block, right_block);
255
256
output_block = IPinv(block);
257
258
return output_block;
259
260
261
test_block = [0, 0, 1, 0, 1, 0, 0, 0]
262
print "original block: ", test_block
263
key = [1, 1, 0, 0, 0, 1, 1, 1, 1, 0]
264
265
cipher = SDESEncrypt(test_block, key);
266
print "Encrypted block: ", (cipher)
267
268
first_round = [0, 0, 1, 0, 0, 0, 1, 0]
269
k1 = [1, 1, 1, 0, 1, 0, 0, 1]
270
plain = Reverse_First_Round_Encrypt(first_round, k1)
271
print "Plain: ", plain
272
273
274
275
276