Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // This package implements Bruce Schneier's Twofish encryption algorithm. | 5 // This package implements Bruce Schneier's Twofish encryption algorithm. |
6 package twofish | 6 package twofish |
7 | 7 |
8 // Twofish is defined in http://www.schneier.com/paper-twofish-paper.pdf [TWOFIS H] | 8 // Twofish is defined in http://www.schneier.com/paper-twofish-paper.pdf [TWOFIS H] |
9 // The code is a port of the LibTom C implementation. | 9 // The code is a port of the LibTom C implementation. |
10 // See http://libtom.org/?page=features&newsitems=5&whatfile=crypt. | 10 // See http://libtom.org/?page=features&newsitems=5&whatfile=crypt. |
11 // LibTomCrypt is free for all purposes under the public domain. | 11 // LibTomCrypt is free for all purposes under the public domain. |
12 // It was heavily inspired by the go blowfish package. | 12 // It was heavily inspired by the go blowfish package. |
13 | 13 |
14 import ( | 14 import ( |
15 "os" | 15 "os" |
16 "strconv" | 16 "strconv" |
17 ) | 17 ) |
18 | 18 |
19 // 16, 32 min/max keysize (octets) | |
20 // 16, 16 block size (octets), default number of rounds | |
21 | |
22 // BlockSize is the constant block size of Twofish.· | 19 // BlockSize is the constant block size of Twofish.· |
23 const BlockSize = 16 | 20 const BlockSize = 16 |
24 | 21 |
25 const mdsPolynomial = 0x169 // x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2 | 22 const mdsPolynomial = 0x169 // x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2 |
26 const rsPolynomial = 0x14d // x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3 | 23 const rsPolynomial = 0x14d // x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3 |
27 | 24 |
28 // A Cipher is an instance of Twofish encryption using a particular key. | 25 // A Cipher is an instance of Twofish encryption using a particular key. |
29 type Cipher struct { | 26 type Cipher struct { |
30 s [4][256]uint32 | 27 s [4][256]uint32 |
31 k [40]uint32 | 28 k [40]uint32 |
32 } | 29 } |
33 | 30 |
34 type KeySizeError int | 31 type KeySizeError int |
35 | 32 |
36 func (k KeySizeError) String() string { | 33 func (k KeySizeError) String() string { |
37 return "crypto/twofish: invalid key size " + strconv.Itoa(int(k)) | 34 return "crypto/twofish: invalid key size " + strconv.Itoa(int(k)) |
38 } | 35 } |
39 | 36 |
40 // NewCipher creates and returns a Cipher. | 37 // NewCipher creates and returns a Cipher. |
41 // The key argument should be the Twofish key, 16, 24 or 32 bytes. | 38 // The key argument should be the Twofish key, 16, 24 or 32 bytes. |
42 func NewCipher(key []byte) (*Cipher, os.Error) { | 39 func NewCipher(key []byte) (*Cipher, os.Error) { |
43 keylen := len(key) | 40 keylen := len(key) |
44 | 41 |
45 if keylen != 16 && keylen != 24 && keylen != 32 { | 42 if keylen != 16 && keylen != 24 && keylen != 32 { |
46 return nil, KeySizeError(keylen) | 43 return nil, KeySizeError(keylen) |
47 } | 44 } |
48 | 45 |
49 // k is the number of 64 bit words in key | 46 // k is the number of 64 bit words in key |
50 k := keylen / 8 | 47 k := keylen / 8 |
51 | 48 |
52 // Create the S[..] words | 49 // Create the S[..] words |
53 var S [4 * 4]byte | 50 var S [4 * 4]byte |
54 for i := 0; i < k; i++ { | 51 for i := 0; i < k; i++ { |
55 // Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7] | 52 // Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7] |
56 » » for j := 0; j < 4; j++ { | 53 » » for j := range rs { |
57 » » » for k := 0; k < 8; k++ { | 54 » » » for k := range rs[j] { |
58 S[4*i+j] ^= gfMult(key[8*i+k], rs[j][k], rsPolyn omial) | 55 S[4*i+j] ^= gfMult(key[8*i+k], rs[j][k], rsPolyn omial) |
59 } | 56 } |
60 } | 57 } |
61 } | 58 } |
62 | 59 |
63 // Calculate subkeys | 60 // Calculate subkeys |
64 c := new(Cipher) | 61 c := new(Cipher) |
65 var tmp [4]byte | 62 var tmp [4]byte |
66 for i := byte(0); i < 20; i++ { | 63 for i := byte(0); i < 20; i++ { |
67 // A = h(p * 2x, Me) | 64 // A = h(p * 2x, Me) |
68 » » for j := 0; j < 4; j++ { | 65 » » for j := range tmp { |
69 tmp[j] = 2 * i | 66 tmp[j] = 2 * i |
70 } | 67 } |
71 A := h(tmp[:], key, 0) | 68 A := h(tmp[:], key, 0) |
72 | 69 |
73 // B = rolc(h(p * (2x + 1), Mo), 8) | 70 // B = rolc(h(p * (2x + 1), Mo), 8) |
74 » » for j := 0; j < 4; j++ { | 71 » » for j := range tmp { |
75 tmp[j] = 2*i + 1 | 72 tmp[j] = 2*i + 1 |
76 } | 73 } |
77 B := h(tmp[:], key, 1) | 74 B := h(tmp[:], key, 1) |
78 B = rol(B, 8) | 75 B = rol(B, 8) |
79 | 76 |
80 c.k[2*i] = A + B | 77 c.k[2*i] = A + B |
81 | |
82 // K[2i+1] = (A + 2B) <<< 9 | |
83 c.k[2*i+1] = rol(2*B+A, 9) | 78 c.k[2*i+1] = rol(2*B+A, 9) |
84 } | 79 } |
85 | 80 |
86 // Calculate sboxes | 81 // Calculate sboxes |
87 switch k { | 82 switch k { |
88 case 2: | 83 case 2: |
89 » » for i := 0; i <= 255; i++ { | 84 » » for i := range c.s[0] { |
rsc
2011/01/19 19:41:08
weird way to write the loop.
better
for i := rang
| |
90 c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i )]^S[0]]^S[4]], 0) | 85 c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i )]^S[0]]^S[4]], 0) |
91 c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i )]^S[1]]^S[5]], 1) | 86 c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i )]^S[1]]^S[5]], 1) |
92 c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i )]^S[2]]^S[6]], 2) | 87 c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i )]^S[2]]^S[6]], 2) |
93 c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i )]^S[3]]^S[7]], 3) | 88 c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i )]^S[3]]^S[7]], 3) |
94 } | 89 } |
95 case 3: | 90 case 3: |
96 » » for i := 0; i < 256; i++ { | 91 » » for i := range c.s[0] { |
rsc
2011/01/19 19:41:08
for i := range c.s[0] {
| |
97 c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1 ][byte(i)]^S[0]]^S[4]]^S[8]], 0) | 92 c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1 ][byte(i)]^S[0]]^S[4]]^S[8]], 0) |
98 c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1 ][byte(i)]^S[1]]^S[5]]^S[9]], 1) | 93 c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1 ][byte(i)]^S[1]]^S[5]]^S[9]], 1) |
99 c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0 ][byte(i)]^S[2]]^S[6]]^S[10]], 2) | 94 c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0 ][byte(i)]^S[2]]^S[6]]^S[10]], 2) |
100 c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0 ][byte(i)]^S[3]]^S[7]]^S[11]], 3) | 95 c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0 ][byte(i)]^S[3]]^S[7]]^S[11]], 3) |
101 } | 96 } |
102 default: | 97 default: |
103 » » for i := 0; i < 256; i++ { | 98 » » for i := range c.s[0] { |
rsc
2011/01/19 19:41:08
for i := range c.s[0] {
| |
104 c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1 ][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0) | 99 c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1 ][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0) |
105 c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1 ][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1) | 100 c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1 ][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1) |
106 c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0 ][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2) | 101 c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0 ][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2) |
107 c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0 ][sbox[1][byte(i)]^S[3]]^S[7]]^S[11]]^S[15]], 3) | 102 c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0 ][sbox[1][byte(i)]^S[3]]^S[7]]^S[11]]^S[15]], 3) |
108 } | 103 } |
109 } | 104 } |
110 | 105 |
111 return c, nil | 106 return c, nil |
112 } | 107 } |
113 | 108 |
114 // Reset zeros the key data, so that it will | 109 // Reset zeros the key data, so that it will no longer appear in the process's |
115 // no longer appear in the process's memory. | 110 // memory. |
116 func (c *Cipher) Reset() { | 111 func (c *Cipher) Reset() { |
117 » for i := 0; i < 40; i++ { | 112 » for i := range c.k { |
rsc
2011/01/19 19:41:08
for i := range c.k {
| |
118 c.k[i] = 0 | 113 c.k[i] = 0 |
119 } | 114 } |
120 » for i := 0; i < 4; i++ { | 115 » for i := range c.s { |
rsc
2011/01/19 19:41:08
for i := range c.s {
| |
121 » » for j := 0; j < 265; j++ { | 116 » » for j := range c.s[i] { |
rsc
2011/01/19 19:41:08
for j := range c.s[i] {
(avoids typo 265)
| |
122 c.s[i][j] = 0 | 117 c.s[i][j] = 0 |
123 } | 118 } |
124 } | 119 } |
125 } | 120 } |
126 | 121 |
127 // BlockSize returns the Twofish block size, 16 bytes. | 122 // BlockSize returns the Twofish block size, 16 bytes. |
128 func (c *Cipher) BlockSize() int { return BlockSize } | 123 func (c *Cipher) BlockSize() int { return BlockSize } |
129 | 124 |
130 // store32l stores src in dst in little-endian form. | 125 // store32l stores src in dst in little-endian form. |
131 func store32l(dst []byte, src uint32) { | 126 func store32l(dst []byte, src uint32) { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
208 // branchless GF multiplier | 203 // branchless GF multiplier |
209 for i := 0; i < 7; i++ { | 204 for i := 0; i < 7; i++ { |
210 result ^= B[a&1] | 205 result ^= B[a&1] |
211 a >>= 1 | 206 a >>= 1 |
212 B[1] = P[B[1]>>7] ^ (B[1] << 1) | 207 B[1] = P[B[1]>>7] ^ (B[1] << 1) |
213 } | 208 } |
214 result ^= B[a&1] | 209 result ^= B[a&1] |
215 return byte(result) | 210 return byte(result) |
216 } | 211 } |
217 | 212 |
218 // [y0 y1 y2 y3] = MDS . [x0] | 213 // mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS · [x0] |
219 func mdsColumnMult(in byte, col int) uint32 { | 214 func mdsColumnMult(in byte, col int) uint32 { |
220 mul01 := in | 215 mul01 := in |
221 mul5B := gfMult(in, 0x5B, mdsPolynomial) | 216 mul5B := gfMult(in, 0x5B, mdsPolynomial) |
222 mulEF := gfMult(in, 0xEF, mdsPolynomial) | 217 mulEF := gfMult(in, 0xEF, mdsPolynomial) |
223 | 218 |
224 switch col { | 219 switch col { |
225 case 0: | 220 case 0: |
226 return uint32(mul01) | uint32(mul5B)<<8 | uint32(mulEF)<<16 | ui nt32(mulEF)<<24 | 221 return uint32(mul01) | uint32(mul5B)<<8 | uint32(mulEF)<<16 | ui nt32(mulEF)<<24 |
227 case 1: | 222 case 1: |
228 return uint32(mulEF) | uint32(mulEF)<<8 | uint32(mul5B)<<16 | ui nt32(mul01)<<24 | 223 return uint32(mulEF) | uint32(mulEF)<<8 | uint32(mul5B)<<16 | ui nt32(mul01)<<24 |
229 case 2: | 224 case 2: |
230 return uint32(mul5B) | uint32(mulEF)<<8 | uint32(mul01)<<16 | ui nt32(mulEF)<<24 | 225 return uint32(mul5B) | uint32(mulEF)<<8 | uint32(mul01)<<16 | ui nt32(mulEF)<<24 |
231 case 3: | 226 case 3: |
232 return uint32(mul5B) | uint32(mul01)<<8 | uint32(mulEF)<<16 | ui nt32(mul5B)<<24 | 227 return uint32(mul5B) | uint32(mul01)<<8 | uint32(mulEF)<<16 | ui nt32(mul5B)<<24 |
233 } | 228 } |
234 | 229 |
235 panic("unreachable") | 230 panic("unreachable") |
236 } | 231 } |
237 | 232 |
238 // h implements the S-box generation function. See [TWOFISH] 4.3.5 | 233 // h implements the sbox generation function. See [TWOFISH] 4.3.5 |
239 func h(in, key []byte, offset int) uint32 { | 234 func h(in, key []byte, offset int) uint32 { |
240 var y [4]byte | 235 var y [4]byte |
241 » for x := 0; x < 4; x++ { | 236 » for x := range y { |
242 y[x] = in[x] | 237 y[x] = in[x] |
243 } | 238 } |
244 switch len(key) / 8 { | 239 switch len(key) / 8 { |
245 case 4: | 240 case 4: |
246 y[0] = sbox[1][y[0]] ^ key[4*(6+offset)+0] | 241 y[0] = sbox[1][y[0]] ^ key[4*(6+offset)+0] |
247 y[1] = sbox[0][y[1]] ^ key[4*(6+offset)+1] | 242 y[1] = sbox[0][y[1]] ^ key[4*(6+offset)+1] |
248 y[2] = sbox[0][y[2]] ^ key[4*(6+offset)+2] | 243 y[2] = sbox[0][y[2]] ^ key[4*(6+offset)+2] |
249 y[3] = sbox[1][y[3]] ^ key[4*(6+offset)+3] | 244 y[3] = sbox[1][y[3]] ^ key[4*(6+offset)+3] |
250 fallthrough | 245 fallthrough |
251 case 3: | 246 case 3: |
252 y[0] = sbox[1][y[0]] ^ key[4*(4+offset)+0] | 247 y[0] = sbox[1][y[0]] ^ key[4*(4+offset)+0] |
253 y[1] = sbox[1][y[1]] ^ key[4*(4+offset)+1] | 248 y[1] = sbox[1][y[1]] ^ key[4*(4+offset)+1] |
254 y[2] = sbox[0][y[2]] ^ key[4*(4+offset)+2] | 249 y[2] = sbox[0][y[2]] ^ key[4*(4+offset)+2] |
255 y[3] = sbox[0][y[3]] ^ key[4*(4+offset)+3] | 250 y[3] = sbox[0][y[3]] ^ key[4*(4+offset)+3] |
256 fallthrough | 251 fallthrough |
257 case 2: | 252 case 2: |
258 y[0] = sbox[1][sbox[0][sbox[0][y[0]]^key[4*(2+offset)+0]]^key[4* (0+offset)+0]] | 253 y[0] = sbox[1][sbox[0][sbox[0][y[0]]^key[4*(2+offset)+0]]^key[4* (0+offset)+0]] |
259 y[1] = sbox[0][sbox[0][sbox[1][y[1]]^key[4*(2+offset)+1]]^key[4* (0+offset)+1]] | 254 y[1] = sbox[0][sbox[0][sbox[1][y[1]]^key[4*(2+offset)+1]]^key[4* (0+offset)+1]] |
260 y[2] = sbox[1][sbox[1][sbox[0][y[2]]^key[4*(2+offset)+2]]^key[4* (0+offset)+2]] | 255 y[2] = sbox[1][sbox[1][sbox[0][y[2]]^key[4*(2+offset)+2]]^key[4* (0+offset)+2]] |
261 y[3] = sbox[0][sbox[1][sbox[1][y[3]]^key[4*(2+offset)+3]]^key[4* (0+offset)+3]] | 256 y[3] = sbox[0][sbox[1][sbox[1][y[3]]^key[4*(2+offset)+3]]^key[4* (0+offset)+3]] |
262 } | 257 } |
263 // [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] | 258 // [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] |
264 var mdsMult uint32 | 259 var mdsMult uint32 |
265 » for i := 0; i < 4; i++ { | 260 » for i := range y { |
266 mdsMult ^= mdsColumnMult(y[i], i) | 261 mdsMult ^= mdsColumnMult(y[i], i) |
267 } | 262 } |
268 return mdsMult | 263 return mdsMult |
269 } | 264 } |
270 | 265 |
271 // Encrypt encrypts a 16-byte block from src to dst, which may overlap. | 266 // Encrypt encrypts a 16-byte block from src to dst, which may overlap. |
272 // Note that for amounts of data larger than a block, | 267 // Note that for amounts of data larger than a block, |
273 // it is not safe to just call Encrypt on successive blocks; | 268 // it is not safe to just call Encrypt on successive blocks; |
274 // instead, use an encryption mode like CBC (see crypto/block/cbc.go).· | 269 // instead, use an encryption mode like CBC (see crypto/block/cbc.go).· |
275 func (skey *Cipher) Encrypt(dst, src []byte) { | 270 func (c *Cipher) Encrypt(dst, src []byte) { |
rsc
2011/01/19 19:41:08
should be c *Cipher.
skey is an implementation det
| |
276 » S1 := skey.s[0] | 271 » S1 := c.s[0] |
277 » S2 := skey.s[1] | 272 » S2 := c.s[1] |
278 » S3 := skey.s[2] | 273 » S3 := c.s[2] |
279 » S4 := skey.s[3] | 274 » S4 := c.s[3] |
280 | 275 |
281 // Load input | 276 // Load input |
282 » a := load32l(src[0:4]) | 277 » ia := load32l(src[0:4]) |
283 » b := load32l(src[4:8]) | 278 » ib := load32l(src[4:8]) |
284 » c := load32l(src[8:12]) | 279 » ic := load32l(src[8:12]) |
285 » d := load32l(src[12:16]) | 280 » id := load32l(src[12:16]) |
286 | 281 |
287 // Pre-whitening | 282 // Pre-whitening |
288 » a ^= skey.k[0] | 283 » ia ^= c.k[0] |
289 » b ^= skey.k[1] | 284 » ib ^= c.k[1] |
290 » c ^= skey.k[2] | 285 » ic ^= c.k[2] |
291 » d ^= skey.k[3] | 286 » id ^= c.k[3] |
292 | 287 |
293 for i := 0; i < 8; i++ { | 288 for i := 0; i < 8; i++ { |
294 » » k := skey.k[8+i*4 : 12+i*4] | 289 » » k := c.k[8+i*4 : 12+i*4] |
295 » » t2 := S2[byte(b)] ^ S3[byte(b>>8)] ^ S4[byte(b>>16)] ^ S1[byte(b >>24)] | 290 » » t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byt e(ib>>24)] |
296 » » t1 := S1[byte(a)] ^ S2[byte(a>>8)] ^ S3[byte(a>>16)] ^ S4[byte(a >>24)] + t2 | 291 » » t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byt e(ia>>24)] + t2 |
297 » » c = ror(c^(t1+k[0]), 1) | 292 » » ic = ror(ic^(t1+k[0]), 1) |
298 » » d = rol(d, 1) ^ (t2 + t1 + k[1]) | 293 » » id = rol(id, 1) ^ (t2 + t1 + k[1]) |
299 | 294 |
300 » » t2 = S2[byte(d)] ^ S3[byte(d>>8)] ^ S4[byte(d>>16)] ^ S1[byte(d> >24)] | 295 » » t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte (id>>24)] |
301 » » t1 = S1[byte(c)] ^ S2[byte(c>>8)] ^ S3[byte(c>>16)] ^ S4[byte(c> >24)] + t2 | 296 » » t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte (ic>>24)] + t2 |
302 » » a = ror(a^(t1+k[2]), 1) | 297 » » ia = ror(ia^(t1+k[2]), 1) |
303 » » b = rol(b, 1) ^ (t2 + t1 + k[3]) | 298 » » ib = rol(ib, 1) ^ (t2 + t1 + k[3]) |
304 } | 299 } |
305 | 300 |
306 // Output with "undo last swap" | 301 // Output with "undo last swap" |
307 » ta := c ^ skey.k[4] | 302 » ta := ic ^ c.k[4] |
308 » tb := d ^ skey.k[5] | 303 » tb := id ^ c.k[5] |
309 » tc := a ^ skey.k[6] | 304 » tc := ia ^ c.k[6] |
310 » td := b ^ skey.k[7] | 305 » td := ib ^ c.k[7] |
311 | 306 |
312 store32l(dst[0:4], ta) | 307 store32l(dst[0:4], ta) |
313 store32l(dst[4:8], tb) | 308 store32l(dst[4:8], tb) |
314 store32l(dst[8:12], tc) | 309 store32l(dst[8:12], tc) |
315 store32l(dst[12:16], td) | 310 store32l(dst[12:16], td) |
316 } | 311 } |
317 | 312 |
318 // Decrypt decrypts a 16-byte block from src to dst, which may overlap. | 313 // Decrypt decrypts a 16-byte block from src to dst, which may overlap. |
319 func (skey *Cipher) Decrypt(dst, src []byte) { | 314 func (c *Cipher) Decrypt(dst, src []byte) { |
rsc
2011/01/19 19:41:08
c *Cipher
| |
320 » S1 := skey.s[0] | 315 » S1 := c.s[0] |
321 » S2 := skey.s[1] | 316 » S2 := c.s[1] |
322 » S3 := skey.s[2] | 317 » S3 := c.s[2] |
323 » S4 := skey.s[3] | 318 » S4 := c.s[3] |
324 | 319 |
325 // Load input | 320 // Load input |
326 ta := load32l(src[0:4]) | 321 ta := load32l(src[0:4]) |
327 tb := load32l(src[4:8]) | 322 tb := load32l(src[4:8]) |
328 tc := load32l(src[8:12]) | 323 tc := load32l(src[8:12]) |
329 td := load32l(src[12:16]) | 324 td := load32l(src[12:16]) |
330 | 325 |
331 // Undo undo final swap | 326 // Undo undo final swap |
332 » a := tc ^ skey.k[6] | 327 » ia := tc ^ c.k[6] |
333 » b := td ^ skey.k[7] | 328 » ib := td ^ c.k[7] |
334 » c := ta ^ skey.k[4] | 329 » ic := ta ^ c.k[4] |
335 » d := tb ^ skey.k[5] | 330 » id := tb ^ c.k[5] |
336 | 331 |
337 for i := 8; i > 0; i-- { | 332 for i := 8; i > 0; i-- { |
338 » » k := skey.k[4+i*4 : 8+i*4] | 333 » » k := c.k[4+i*4 : 8+i*4] |
339 » » t2 := S2[byte(d)] ^ S3[byte(d>>8)] ^ S4[byte(d>>16)] ^ S1[byte(d >>24)] | 334 » » t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byt e(id>>24)] |
340 » » t1 := S1[byte(c)] ^ S2[byte(c>>8)] ^ S3[byte(c>>16)] ^ S4[byte(c >>24)] + t2 | 335 » » t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byt e(ic>>24)] + t2 |
341 » » a = rol(a, 1) ^ (t1 + k[2]) | 336 » » ia = rol(ia, 1) ^ (t1 + k[2]) |
342 » » b = ror(b^(t2+t1+k[3]), 1) | 337 » » ib = ror(ib^(t2+t1+k[3]), 1) |
343 | 338 |
344 » » t2 = S2[byte(b)] ^ S3[byte(b>>8)] ^ S4[byte(b>>16)] ^ S1[byte(b> >24)] | 339 » » t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte (ib>>24)] |
345 » » t1 = S1[byte(a)] ^ S2[byte(a>>8)] ^ S3[byte(a>>16)] ^ S4[byte(a> >24)] + t2 | 340 » » t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte (ia>>24)] + t2 |
346 » » c = rol(c, 1) ^ (t1 + k[0]) | 341 » » ic = rol(ic, 1) ^ (t1 + k[0]) |
347 » » d = ror(d^(t2+t1+k[1]), 1) | 342 » » id = ror(id^(t2+t1+k[1]), 1) |
348 } | 343 } |
349 | 344 |
350 // Undo pre-whitening | 345 // Undo pre-whitening |
351 » a ^= skey.k[0] | 346 » ia ^= c.k[0] |
352 » b ^= skey.k[1] | 347 » ib ^= c.k[1] |
353 » c ^= skey.k[2] | 348 » ic ^= c.k[2] |
354 » d ^= skey.k[3] | 349 » id ^= c.k[3] |
355 | 350 |
356 » store32l(dst[0:4], a) | 351 » store32l(dst[0:4], ia) |
357 » store32l(dst[4:8], b) | 352 » store32l(dst[4:8], ib) |
358 » store32l(dst[8:12], c) | 353 » store32l(dst[8:12], ic) |
359 » store32l(dst[12:16], d) | 354 » store32l(dst[12:16], id) |
360 } | 355 } |
LEFT | RIGHT |