Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(44)

Delta Between Two Patch Sets: src/pkg/crypto/twofish/twofish.go

Issue 2687042: code review 2687042: Additional crypto library: Schneier's Twofish
Left Patch Set: code review 2687042: Additional crypto library: Schneier's Twofish Created 14 years, 2 months ago
Right Patch Set: code review 2687042: Additional crypto library: Schneier's Twofish Created 14 years, 2 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | src/pkg/crypto/twofish/twofish_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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
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 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b