...
1
2
3
4
5 package des
6
7 import "encoding/binary"
8
9 func cryptBlock(subkeys []uint64, dst, src []byte, decrypt bool) {
10 b := binary.BigEndian.Uint64(src)
11 b = permuteInitialBlock(b)
12 left, right := uint32(b>>32), uint32(b)
13
14 left = (left << 1) | (left >> 31)
15 right = (right << 1) | (right >> 31)
16
17 if decrypt {
18 for i := 0; i < 8; i++ {
19 left, right = feistel(left, right, subkeys[15-2*i], subkeys[15-(2*i+1)])
20 }
21 } else {
22 for i := 0; i < 8; i++ {
23 left, right = feistel(left, right, subkeys[2*i], subkeys[2*i+1])
24 }
25 }
26
27 left = (left << 31) | (left >> 1)
28 right = (right << 31) | (right >> 1)
29
30
31 preOutput := (uint64(right) << 32) | uint64(left)
32 binary.BigEndian.PutUint64(dst, permuteFinalBlock(preOutput))
33 }
34
35
36 func encryptBlock(subkeys []uint64, dst, src []byte) {
37 cryptBlock(subkeys, dst, src, false)
38 }
39
40
41 func decryptBlock(subkeys []uint64, dst, src []byte) {
42 cryptBlock(subkeys, dst, src, true)
43 }
44
45
46 func feistel(l, r uint32, k0, k1 uint64) (lout, rout uint32) {
47 var t uint32
48
49 t = r ^ uint32(k0>>32)
50 l ^= feistelBox[7][t&0x3f] ^
51 feistelBox[5][(t>>8)&0x3f] ^
52 feistelBox[3][(t>>16)&0x3f] ^
53 feistelBox[1][(t>>24)&0x3f]
54
55 t = ((r << 28) | (r >> 4)) ^ uint32(k0)
56 l ^= feistelBox[6][(t)&0x3f] ^
57 feistelBox[4][(t>>8)&0x3f] ^
58 feistelBox[2][(t>>16)&0x3f] ^
59 feistelBox[0][(t>>24)&0x3f]
60
61 t = l ^ uint32(k1>>32)
62 r ^= feistelBox[7][t&0x3f] ^
63 feistelBox[5][(t>>8)&0x3f] ^
64 feistelBox[3][(t>>16)&0x3f] ^
65 feistelBox[1][(t>>24)&0x3f]
66
67 t = ((l << 28) | (l >> 4)) ^ uint32(k1)
68 r ^= feistelBox[6][(t)&0x3f] ^
69 feistelBox[4][(t>>8)&0x3f] ^
70 feistelBox[2][(t>>16)&0x3f] ^
71 feistelBox[0][(t>>24)&0x3f]
72
73 return l, r
74 }
75
76
77
78 var feistelBox [8][64]uint32
79
80
81 func permuteBlock(src uint64, permutation []uint8) (block uint64) {
82 for position, n := range permutation {
83 bit := (src >> n) & 1
84 block |= bit << uint((len(permutation)-1)-position)
85 }
86 return
87 }
88
89 func init() {
90 for s := range sBoxes {
91 for i := 0; i < 4; i++ {
92 for j := 0; j < 16; j++ {
93 f := uint64(sBoxes[s][i][j]) << (4 * (7 - uint(s)))
94 f = permuteBlock(f, permutationFunction[:])
95
96
97
98 row := uint8(((i & 2) << 4) | i&1)
99 col := uint8(j << 1)
100 t := row | col
101
102
103 f = (f << 1) | (f >> 31)
104
105 feistelBox[s][t] = uint32(f)
106 }
107 }
108 }
109 }
110
111
112
113 func permuteInitialBlock(block uint64) uint64 {
114
115 b1 := block >> 48
116 b2 := block << 48
117 block ^= b1 ^ b2 ^ b1<<48 ^ b2>>48
118
119
120 b1 = block >> 32 & 0xff00ff
121 b2 = (block & 0xff00ff00)
122 block ^= b1<<32 ^ b2 ^ b1<<8 ^ b2<<24
123
124
125
126
127
128
129
130
131
132
133
134
135 b1 = block & 0x0f0f00000f0f0000
136 b2 = block & 0x0000f0f00000f0f0
137 block ^= b1 ^ b2 ^ b1>>12 ^ b2<<12
138
139
140
141
142
143
144
145
146
147
148
149 b1 = block & 0x3300330033003300
150 b2 = block & 0x00cc00cc00cc00cc
151 block ^= b1 ^ b2 ^ b1>>6 ^ b2<<6
152
153
154
155
156
157
158
159
160
161
162
163
164 b1 = block & 0xaaaaaaaa55555555
165 block ^= b1 ^ b1>>33 ^ b1<<33
166
167
168
169
170
171
172
173
174
175
176 return block
177 }
178
179
180
181 func permuteFinalBlock(block uint64) uint64 {
182
183
184 b1 := block & 0xaaaaaaaa55555555
185 block ^= b1 ^ b1>>33 ^ b1<<33
186
187 b1 = block & 0x3300330033003300
188 b2 := block & 0x00cc00cc00cc00cc
189 block ^= b1 ^ b2 ^ b1>>6 ^ b2<<6
190
191 b1 = block & 0x0f0f00000f0f0000
192 b2 = block & 0x0000f0f00000f0f0
193 block ^= b1 ^ b2 ^ b1>>12 ^ b2<<12
194
195 b1 = block >> 32 & 0xff00ff
196 b2 = (block & 0xff00ff00)
197 block ^= b1<<32 ^ b2 ^ b1<<8 ^ b2<<24
198
199 b1 = block >> 48
200 b2 = block << 48
201 block ^= b1 ^ b2 ^ b1<<48 ^ b2>>48
202 return block
203 }
204
205
206
207 func ksRotate(in uint32) (out []uint32) {
208 out = make([]uint32, 16)
209 last := in
210 for i := 0; i < 16; i++ {
211
212 left := (last << (4 + ksRotations[i])) >> 4
213 right := (last << 4) >> (32 - ksRotations[i])
214 out[i] = left | right
215 last = out[i]
216 }
217 return
218 }
219
220
221 func (c *desCipher) generateSubkeys(keyBytes []byte) {
222
223 key := binary.BigEndian.Uint64(keyBytes)
224 permutedKey := permuteBlock(key, permutedChoice1[:])
225
226
227 leftRotations := ksRotate(uint32(permutedKey >> 28))
228 rightRotations := ksRotate(uint32(permutedKey<<4) >> 4)
229
230
231 for i := 0; i < 16; i++ {
232
233 pc2Input := uint64(leftRotations[i])<<28 | uint64(rightRotations[i])
234
235 c.subkeys[i] = unpack(permuteBlock(pc2Input, permutedChoice2[:]))
236 }
237 }
238
239
240
241
242 func unpack(x uint64) uint64 {
243 var result uint64
244
245 result = ((x>>(6*1))&0xff)<<(8*0) |
246 ((x>>(6*3))&0xff)<<(8*1) |
247 ((x>>(6*5))&0xff)<<(8*2) |
248 ((x>>(6*7))&0xff)<<(8*3) |
249 ((x>>(6*0))&0xff)<<(8*4) |
250 ((x>>(6*2))&0xff)<<(8*5) |
251 ((x>>(6*4))&0xff)<<(8*6) |
252 ((x>>(6*6))&0xff)<<(8*7)
253
254 return result
255 }
256
View as plain text