LEFT | RIGHT |
(no file at all) | |
| 1 // Copyright 2012 The Go Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style |
| 3 // license that can be found in the LICENSE file. |
| 4 |
| 5 // Package scrypt implements the scrypt key derivation function as defined in |
| 6 // Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard |
| 7 // Functions" (http://www.tarsnap.com/scrypt/scrypt.pdf). |
| 8 package scrypt |
| 9 |
| 10 import ( |
| 11 "crypto/sha256" |
| 12 "encoding/binary" |
| 13 "errors" |
| 14 |
| 15 "code.google.com/p/go.crypto/pbkdf2" |
| 16 "code.google.com/p/go.crypto/salsa20/salsa" |
| 17 ) |
| 18 |
| 19 const maxInt = int(^uint(0) >> 1) |
| 20 |
| 21 // blockCopy copies n bytes from src into dst. |
| 22 func blockCopy(dst, src []byte, n int) { |
| 23 copy(dst, src[:n]) |
| 24 } |
| 25 |
| 26 // blockXOR XORs bytes from dst with n bytes from src. |
| 27 func blockXOR(dst, src []byte, n int) { |
| 28 for i, v := range src[:n] { |
| 29 dst[i] ^= v |
| 30 } |
| 31 } |
| 32 |
| 33 func blockMix(b, y []byte, r int) { |
| 34 var x [64]byte |
| 35 |
| 36 blockCopy(x[:], b[(2*r-1)*64:], 64) |
| 37 |
| 38 for i := 0; i < 2*r*64; i += 64 { |
| 39 blockXOR(x[:], b[i:], 64) |
| 40 salsa.Core208(&x, &x) |
| 41 blockCopy(y[i:], x[:], 64) |
| 42 } |
| 43 |
| 44 for i := 0; i < r; i++ { |
| 45 blockCopy(b[i*64:], y[i*2*64:], 64) |
| 46 } |
| 47 |
| 48 for i := 0; i < r; i++ { |
| 49 blockCopy(b[(i+r)*64:], y[(i*2+1)*64:], 64) |
| 50 } |
| 51 } |
| 52 |
| 53 func integer(b []byte, r int) uint64 { |
| 54 return binary.LittleEndian.Uint64(b[(2*r-1)*64:]) |
| 55 } |
| 56 |
| 57 func smix(b []byte, r, N int, v, xy []byte) { |
| 58 x := xy |
| 59 y := xy[128*r:] |
| 60 |
| 61 blockCopy(x, b, 128*r) |
| 62 |
| 63 for i := 0; i < N; i++ { |
| 64 blockCopy(v[i*128*r:], x, 128*r) |
| 65 blockMix(x, y, r) |
| 66 } |
| 67 |
| 68 for i := 0; i < N; i++ { |
| 69 j := int(integer(x, r) & uint64(N-1)) |
| 70 blockXOR(x, v[j*128*r:], 128*r) |
| 71 blockMix(x, y, r) |
| 72 } |
| 73 |
| 74 blockCopy(b, x, 128*r) |
| 75 } |
| 76 |
| 77 // Key derives a key from the password, salt, and cost parameters, returning |
| 78 // a byte slice of length keyLen that can be used as cryptographic key. |
| 79 //· |
| 80 // N is a CPU/memory cost parameter, which must be a power of two greater than 1
. |
| 81 // r and p must satisfy r * p < 2³⁰. If the parameters do not satisfy the |
| 82 // limits, the function returns a nil byte slice and an error. |
| 83 // |
| 84 // For example, you can get a derived key for e.g. AES-256 (which needs a |
| 85 // 32-byte key) by doing: |
| 86 // |
| 87 // dk := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32) |
| 88 // |
| 89 // The recommended parameters for interactive logins as of 2009 are N=16384, |
| 90 // r=8, p=1. They should be increased as memory latency and CPU parallelism |
| 91 // increases. Remember to get a good random salt. |
| 92 func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) { |
| 93 if N <= 1 || N&(N-1) != 0 { |
| 94 return nil, errors.New("scrypt: N must be > 1 and a power of 2") |
| 95 } |
| 96 if uint64(r)*uint64(p) >= 1<<30 || r > maxInt/128/p || r > maxInt/256 ||
N > maxInt/128/r { |
| 97 return nil, errors.New("scrypt: parameters are too large") |
| 98 } |
| 99 |
| 100 xy := make([]byte, 256*r) |
| 101 v := make([]byte, 128*r*N) |
| 102 b := pbkdf2.Key(password, salt, 1, p*128*r, sha256.New) |
| 103 |
| 104 for i := 0; i < p; i++ { |
| 105 smix(b[i*128*r:], r, N, v, xy) |
| 106 } |
| 107 |
| 108 return pbkdf2.Key(password, b, 1, keyLen, sha256.New), nil |
| 109 } |
LEFT | RIGHT |