1
- // Copyright 2012 Dmitry Chestnykh (Go implementation)
2
- // Copyright 2009 Colin Percival (original C implementation)
3
- // All rights reserved.
1
+ // Copyright 2012 The Go Authors. All rights reserved.
4
2
// Use of this source code is governed by a BSD-style
5
3
// license that can be found in the LICENSE file.
6
4
7
5
// Package scrypt implements the scrypt key derivation function as defined in
8
6
// Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard
9
- // Functions".
7
+ // Functions" (http://www.tarsnap.com/scrypt/scrypt.pdf) .
10
8
package scrypt
11
9
12
10
import (
13
11
"crypto/sha256"
14
- "encoding/binary"
15
12
"errors"
16
13
17
14
"code.google.com/p/go.crypto/pbkdf2"
18
15
)
19
16
20
- const maxInt = 1 << 31 - 1
17
+ const maxInt = int ( ^ uint ( 0 ) >> 1 )
21
18
22
- // blockCopy copies n bytes from src into dst.
23
- func blockCopy (dst , src []byte , n int ) {
19
+ // blockCopy copies n numbers from src into dst.
20
+ func blockCopy (dst , src []uint32 , n int ) {
24
21
copy (dst , src [:n ])
25
22
}
26
23
27
- // blockXOR XORs bytes from dst with n bytes from src.
28
- func blockXOR (dst , src []byte , n int ) {
24
+ // blockXOR XORs numbers from dst with n numbers from src.
25
+ func blockXOR (dst , src []uint32 , n int ) {
29
26
for i , v := range src [:n ] {
30
27
dst [i ] ^= v
31
28
}
32
29
}
33
30
34
- // salsa applies Salsa20/8 to the given array.
35
- func salsa (b * [64 ]byte ) {
36
- w0 := uint32 (b [0 ]) | uint32 (b [1 ])<< 8 | uint32 (b [2 ])<< 16 | uint32 (b [3 ])<< 24
37
- w1 := uint32 (b [4 ]) | uint32 (b [5 ])<< 8 | uint32 (b [6 ])<< 16 | uint32 (b [7 ])<< 24
38
- w2 := uint32 (b [8 ]) | uint32 (b [9 ])<< 8 | uint32 (b [10 ])<< 16 | uint32 (b [11 ])<< 24
39
- w3 := uint32 (b [12 ]) | uint32 (b [13 ])<< 8 | uint32 (b [14 ])<< 16 | uint32 (b [15 ])<< 24
40
- w4 := uint32 (b [16 ]) | uint32 (b [17 ])<< 8 | uint32 (b [18 ])<< 16 | uint32 (b [19 ])<< 24
41
- w5 := uint32 (b [20 ]) | uint32 (b [21 ])<< 8 | uint32 (b [22 ])<< 16 | uint32 (b [23 ])<< 24
42
- w6 := uint32 (b [24 ]) | uint32 (b [25 ])<< 8 | uint32 (b [26 ])<< 16 | uint32 (b [27 ])<< 24
43
- w7 := uint32 (b [28 ]) | uint32 (b [29 ])<< 8 | uint32 (b [30 ])<< 16 | uint32 (b [31 ])<< 24
44
- w8 := uint32 (b [32 ]) | uint32 (b [33 ])<< 8 | uint32 (b [34 ])<< 16 | uint32 (b [35 ])<< 24
45
- w9 := uint32 (b [36 ]) | uint32 (b [37 ])<< 8 | uint32 (b [38 ])<< 16 | uint32 (b [39 ])<< 24
46
- w10 := uint32 (b [40 ]) | uint32 (b [41 ])<< 8 | uint32 (b [42 ])<< 16 | uint32 (b [43 ])<< 24
47
- w11 := uint32 (b [44 ]) | uint32 (b [45 ])<< 8 | uint32 (b [46 ])<< 16 | uint32 (b [47 ])<< 24
48
- w12 := uint32 (b [48 ]) | uint32 (b [49 ])<< 8 | uint32 (b [50 ])<< 16 | uint32 (b [51 ])<< 24
49
- w13 := uint32 (b [52 ]) | uint32 (b [53 ])<< 8 | uint32 (b [54 ])<< 16 | uint32 (b [55 ])<< 24
50
- w14 := uint32 (b [56 ]) | uint32 (b [57 ])<< 8 | uint32 (b [58 ])<< 16 | uint32 (b [59 ])<< 24
51
- w15 := uint32 (b [60 ]) | uint32 (b [61 ])<< 8 | uint32 (b [62 ])<< 16 | uint32 (b [63 ])<< 24
31
+ // salsaXOR applies Salsa20/8 to the XOR of 16 numbers from tmp and in,
32
+ // and puts the result into both both tmp and out.
33
+ func salsaXOR (tmp * [16 ]uint32 , in , out []uint32 ) {
34
+ w0 := tmp [0 ] ^ in [0 ]
35
+ w1 := tmp [1 ] ^ in [1 ]
36
+ w2 := tmp [2 ] ^ in [2 ]
37
+ w3 := tmp [3 ] ^ in [3 ]
38
+ w4 := tmp [4 ] ^ in [4 ]
39
+ w5 := tmp [5 ] ^ in [5 ]
40
+ w6 := tmp [6 ] ^ in [6 ]
41
+ w7 := tmp [7 ] ^ in [7 ]
42
+ w8 := tmp [8 ] ^ in [8 ]
43
+ w9 := tmp [9 ] ^ in [9 ]
44
+ w10 := tmp [10 ] ^ in [10 ]
45
+ w11 := tmp [11 ] ^ in [11 ]
46
+ w12 := tmp [12 ] ^ in [12 ]
47
+ w13 := tmp [13 ] ^ in [13 ]
48
+ w14 := tmp [14 ] ^ in [14 ]
49
+ w15 := tmp [15 ] ^ in [15 ]
52
50
53
51
x0 , x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8 := w0 , w1 , w2 , w3 , w4 , w5 , w6 , w7 , w8
54
52
x9 , x10 , x11 , x12 , x13 , x14 , x15 := w9 , w10 , w11 , w12 , w13 , w14 , w15
@@ -143,74 +141,77 @@ func salsa(b *[64]byte) {
143
141
x14 += w14
144
142
x15 += w15
145
143
146
- b [0 ], b [ 1 ], b [ 2 ], b [ 3 ] = byte ( x0 ), byte ( x0 >> 8 ), byte ( x0 >> 16 ), byte ( x0 >> 24 )
147
- b [ 4 ], b [ 5 ], b [ 6 ], b [ 7 ] = byte ( x1 ), byte ( x1 >> 8 ), byte ( x1 >> 16 ), byte ( x1 >> 24 )
148
- b [ 8 ], b [ 9 ], b [ 10 ], b [ 11 ] = byte ( x2 ), byte ( x2 >> 8 ), byte ( x2 >> 16 ), byte ( x2 >> 24 )
149
- b [ 12 ], b [ 13 ], b [ 14 ], b [ 15 ] = byte ( x3 ), byte ( x3 >> 8 ), byte ( x3 >> 16 ), byte ( x3 >> 24 )
150
- b [ 16 ], b [ 17 ], b [ 18 ], b [ 19 ] = byte ( x4 ), byte ( x4 >> 8 ), byte ( x4 >> 16 ), byte ( x4 >> 24 )
151
- b [ 20 ], b [ 21 ], b [ 22 ], b [ 23 ] = byte ( x5 ), byte ( x5 >> 8 ), byte ( x5 >> 16 ), byte ( x5 >> 24 )
152
- b [ 24 ], b [ 25 ], b [ 26 ], b [ 27 ] = byte ( x6 ), byte ( x6 >> 8 ), byte ( x6 >> 16 ), byte ( x6 >> 24 )
153
- b [ 28 ], b [ 29 ], b [ 30 ], b [ 31 ] = byte ( x7 ), byte ( x7 >> 8 ), byte ( x7 >> 16 ), byte ( x7 >> 24 )
154
- b [ 32 ], b [ 33 ], b [ 34 ], b [ 35 ] = byte ( x8 ), byte ( x8 >> 8 ), byte ( x8 >> 16 ), byte ( x8 >> 24 )
155
- b [ 36 ], b [ 37 ], b [ 38 ], b [ 39 ] = byte ( x9 ), byte ( x9 >> 8 ), byte ( x9 >> 16 ), byte ( x9 >> 24 )
156
- b [ 40 ], b [ 41 ], b [ 42 ], b [ 43 ] = byte ( x10 ), byte ( x10 >> 8 ), byte ( x10 >> 16 ), byte ( x10 >> 24 )
157
- b [ 44 ], b [ 45 ], b [ 46 ], b [ 47 ] = byte ( x11 ), byte ( x11 >> 8 ), byte ( x11 >> 16 ), byte ( x11 >> 24 )
158
- b [ 48 ], b [ 49 ], b [ 50 ], b [ 51 ] = byte ( x12 ), byte ( x12 >> 8 ), byte ( x12 >> 16 ), byte ( x12 >> 24 )
159
- b [ 52 ], b [ 53 ], b [ 54 ], b [ 55 ] = byte ( x13 ), byte ( x13 >> 8 ), byte ( x13 >> 16 ), byte ( x13 >> 24 )
160
- b [ 56 ], b [ 57 ], b [ 58 ], b [ 59 ] = byte ( x14 ), byte ( x14 >> 8 ), byte ( x14 >> 16 ), byte ( x14 >> 24 )
161
- b [ 60 ], b [ 61 ], b [ 62 ], b [ 63 ] = byte ( x15 ), byte ( x15 >> 8 ), byte ( x15 >> 16 ), byte ( x15 >> 24 )
144
+ out [0 ], tmp [ 0 ] = x0 , x0
145
+ out [ 1 ], tmp [ 1 ] = x1 , x1
146
+ out [ 2 ], tmp [ 2 ] = x2 , x2
147
+ out [ 3 ], tmp [ 3 ] = x3 , x3
148
+ out [ 4 ], tmp [ 4 ] = x4 , x4
149
+ out [ 5 ], tmp [ 5 ] = x5 , x5
150
+ out [ 6 ], tmp [ 6 ] = x6 , x6
151
+ out [ 7 ], tmp [ 7 ] = x7 , x7
152
+ out [ 8 ], tmp [ 8 ] = x8 , x8
153
+ out [ 9 ], tmp [ 9 ] = x9 , x9
154
+ out [ 10 ], tmp [ 10 ] = x10 , x10
155
+ out [ 11 ], tmp [ 11 ] = x11 , x11
156
+ out [ 12 ], tmp [ 12 ] = x12 , x12
157
+ out [ 13 ], tmp [ 13 ] = x13 , x13
158
+ out [ 14 ], tmp [ 14 ] = x14 , x14
159
+ out [ 15 ], tmp [ 15 ] = x15 , x15
162
160
}
163
161
164
- func blockMix (b , y []byte , r int ) {
165
- var x [64 ]byte
166
- xs := x [:]
167
-
168
- blockCopy (xs , b [(2 * r - 1 )* 64 :], 64 )
169
-
170
- for i := 0 ; i < 2 * r ; i ++ {
171
- blockXOR (xs , b [i * 64 :], 64 )
172
- salsa (& x )
173
-
174
- blockCopy (y [i * 64 :], xs , 64 )
175
- }
176
-
177
- for i := 0 ; i < r ; i ++ {
178
- blockCopy (b [i * 64 :], y [(i * 2 )* 64 :], 64 )
179
- }
180
-
181
- for i := 0 ; i < r ; i ++ {
182
- blockCopy (b [(i + r )* 64 :], y [(i * 2 + 1 )* 64 :], 64 )
162
+ func blockMix (tmp * [16 ]uint32 , in , out []uint32 , r int ) {
163
+ blockCopy (tmp [:], in [(2 * r - 1 )* 16 :], 16 )
164
+ for i := 0 ; i < 2 * r ; i += 2 {
165
+ salsaXOR (tmp , in [i * 16 :], out [i * 8 :])
166
+ salsaXOR (tmp , in [i * 16 + 16 :], out [i * 8 + r * 16 :])
183
167
}
184
168
}
185
169
186
- func integerify (b []byte , r int ) uint64 {
187
- return binary .LittleEndian .Uint64 (b [(2 * r - 1 )* 64 :])
170
+ func integer (b []uint32 , r int ) uint64 {
171
+ j := (2 * r - 1 ) * 16
172
+ return uint64 (b [j ]) | uint64 (b [j + 1 ])<< 32
188
173
}
189
174
190
- func smix (b []byte , r , N int , v , xy []byte ) {
175
+ func smix (b []byte , r , N int , v , xy []uint32 ) {
176
+ var tmp [16 ]uint32
191
177
x := xy
192
- y := xy [128 * r :]
193
-
194
- blockCopy (x , b , 128 * r )
178
+ y := xy [32 * r :]
195
179
196
- for i := 0 ; i < N ; i ++ {
197
- blockCopy (v [i * (128 * r ):], x , 128 * r )
198
- blockMix (x , y , r )
180
+ j := 0
181
+ for i := 0 ; i < 32 * r ; i ++ {
182
+ x [i ] = uint32 (b [j ]) | uint32 (b [j + 1 ])<< 8 | uint32 (b [j + 2 ])<< 16 | uint32 (b [j + 3 ])<< 24
183
+ j += 4
199
184
}
185
+ for i := 0 ; i < N ; i += 2 {
186
+ blockCopy (v [i * (32 * r ):], x , 32 * r )
187
+ blockMix (& tmp , x , y , r )
200
188
201
- for i := 0 ; i < N ; i ++ {
202
- j := int (integerify (x , r ) & uint64 (N - 1 ))
203
- blockXOR (x , v [j * (128 * r ):], 128 * r )
204
- blockMix (x , y , r )
189
+ blockCopy (v [(i + 1 )* (32 * r ):], y , 32 * r )
190
+ blockMix (& tmp , y , x , r )
191
+ }
192
+ for i := 0 ; i < N ; i += 2 {
193
+ j := int (integer (x , r ) & uint64 (N - 1 ))
194
+ blockXOR (x , v [j * (32 * r ):], 32 * r )
195
+ blockMix (& tmp , x , y , r )
196
+
197
+ j = int (integer (y , r ) & uint64 (N - 1 ))
198
+ blockXOR (y , v [j * (32 * r ):], 32 * r )
199
+ blockMix (& tmp , y , x , r )
200
+ }
201
+ j = 0
202
+ for _ , v := range x [:32 * r ] {
203
+ b [j + 0 ] = byte (v >> 0 )
204
+ b [j + 1 ] = byte (v >> 8 )
205
+ b [j + 2 ] = byte (v >> 16 )
206
+ b [j + 3 ] = byte (v >> 24 )
207
+ j += 4
205
208
}
206
-
207
- blockCopy (b , x , 128 * r )
208
209
}
209
210
210
- // Key derives a key from the password, salt and cost parameters, returning a
211
- // byte slice of length keyLen that can be used as cryptographic key.
212
- //
213
- // N is a CPU/memory cost parameter, must be a power of two greater than 1.
211
+ // Key derives a key from the password, salt, and cost parameters, returning
212
+ // a byte slice of length keyLen that can be used as cryptographic key.
213
+ //
214
+ // N is a CPU/memory cost parameter, which must be a power of two greater than 1.
214
215
// r and p must satisfy r * p < 2³⁰. If the parameters do not satisfy the
215
216
// limits, the function returns a nil byte slice and an error.
216
217
//
@@ -230,8 +231,8 @@ func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) {
230
231
return nil , errors .New ("scrypt: parameters are too large" )
231
232
}
232
233
233
- xy := make ([]byte , 256 * r )
234
- v := make ([]byte , 128 * r * N )
234
+ xy := make ([]uint32 , 64 * r )
235
+ v := make ([]uint32 , 32 * N * r )
235
236
b := pbkdf2 .Key (password , salt , 1 , p * 128 * r , sha256 .New )
236
237
237
238
for i := 0 ; i < p ; i ++ {
0 commit comments