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

Delta Between Two Patch Sets: pbkdf2/pbkdf2.go

Issue 5587050: code review 5587050: go.crypto/pbkdf2: New package (Closed)
Left Patch Set: diff -r 943eeb94bdc1 https://code.google.com/p/go.crypto Created 12 years, 2 months ago
Right Patch Set: diff -r 943eeb94bdc1 https://code.google.com/p/go.crypto Created 12 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 | pbkdf2/pbkdf2_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 2012 The Go Authors. All rights reserved. 1 // Copyright 2012 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 /* 5 /*
6 Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC 6 Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC
7 2898 / PKCS #5 v2.0. 7 2898 / PKCS #5 v2.0.
8 8
9 A key derivation function is useful when encrypting data based on a password 9 A key derivation function is useful when encrypting data based on a password
10 or any other not-fully-random data. It uses a pseudorandom function to derive 10 or any other not-fully-random data. It uses a pseudorandom function to derive
11 a secure encryption key based on the password. 11 a secure encryption key based on the password.
12 12
13 While v2.0 of the standard defines only one pseudorandom function to use, 13 While v2.0 of the standard defines only one pseudorandom function to use,
14 HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved 14 HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved
15 Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To 15 Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
16 choose, you can pass the `New` functions from the different SHA packages to 16 choose, you can pass the `New` functions from the different SHA packages to
17 pbkdf2.New: 17 pbkdf2.Key.
18
19 » kdf := pbkdf2.New(sha1.New)
20
21 The above gets you a HMAC-SHA-1 based PBKDF2 key derivation function. To use
22 it, get a good random salt:
23
24 » // A random salt of at least 8 bytes long is recommended
25 » salt := make([]byte, 8)
26 » _, err := rand.Read(salt)» // this is crypto/rand
27 » if err != nil {
28 » » panic(err)
29 » }
30
31 Now you can get a derived key for e.g. AES-256 by doing:
32
33 » // AES-256 has a 32-byte key
34 » dk := kdf([]byte("some password"), salt, 4096, 32)
35
36 Using a higher iteration count will increase the cost of exhaustive search and
37 therefor increases security, but choosing one that's too high might make key
38 derivation take longer.
39 */ 18 */
40 package pbkdf2 19 package pbkdf2
41 20
42 import ( 21 import (
43 "crypto/hmac" 22 "crypto/hmac"
44 "encoding/binary" 23 "encoding/binary"
45 "hash" 24 "hash"
46 ) 25 )
47 26
48 // New creates a Password-Based Key Derivation Function based on HMAC with the 27 // Key derives a key from the password, salt and iteration count, returning a
49 // given hashing function. New(sha1.New) will create a key derivation function 28 // []byte of length keylen that can be used as cryptographic key. The key is
50 // using HMAC-SHA-1 as pseudo-random function, which is the only option given 29 // derived based on the method described as PBKDF2 with the HMAC variant using
51 // in v2.0 of the standard. 30 // the supplied hash function.
52 // 31 //
53 // The returned function takes four arguments; first two of type []byte and 32 // For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you
54 // another two of type int: a password P, salt S, iteration count c and the 33 // can get a derived key for e.g. AES-256 (which needs a 32-byte key) by
55 // value dkLen. It returns a derived key dkLen bytes long. 34 // doing:
56 func New(h func() hash.Hash) func(P, S []byte, c, dkLen int) []byte { 35 //
57 » return func(P, S []byte, c, dkLen int) []byte { 36 // » dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New)
58 » » PRF := hmac.New(h, P) 37 //
59 » » hLen := PRF.Size() 38 // Remember to get a good random salt. At least 8 bytes is recommended by the
60 » » l := (dkLen + hLen - 1) / hLen 39 // RFC.
40 //
41 // Using a higher iteration count will increase the cost of an exhaustive
42 // search but will also make derivation proportionally slower.
43 func Key(password, salt []byte, iter, keylen int, h func() hash.Hash) []byte {
44 » prf := hmac.New(h, password)
45 » hashlen := prf.Size()
46 » nblock := (keylen + hashlen - 1) / hashlen
61 47
62 » » DK := make([]byte, 0, dkLen) 48 » var buf [4]byte
63 » » for block := 1; block <= l; block += 1 { 49 » dk := make([]byte, 0, keylen)
64 » » » // for each block T_i = U_1 ^ U_2 ^ ... ^ U_c 50 » for block := 1; block <= nblock; block++ {
65 » » » // U_1 = PRF(P, S || uint(i)) 51 » » // N.B.: || means concatenation, ^ means XOR
66 » » » PRF.Reset() 52 » » // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
67 » » » PRF.Write(S) 53 » » // U_1 = PRF(password, salt || uint(i))
68 » » » binary.Write(PRF, binary.BigEndian, uint32(block)) 54 » » prf.Reset()
69 » » » U := PRF.Sum(nil) 55 » » prf.Write(salt)
70 » » » T := U 56 » » binary.BigEndian.PutUint32(buf[:], uint32(block))
57 » » prf.Write(buf[:4])
58 » » U := prf.Sum(nil)
59 » » T := U
71 60
72 » » » // U_n = PRF(P, U_(n-1)) 61 » » // U_n = PRF(password, U_(n-1))
73 » » » for n := 2; n <= c; n += 1 { 62 » » for n := 2; n <= iter; n++ {
74 » » » » PRF.Reset() 63 » » » prf.Reset()
75 » » » » PRF.Write(U) 64 » » » prf.Write(U)
76 » » » » U = PRF.Sum(nil) 65 » » » U = prf.Sum(nil)
77 » » » » for x := range U { 66 » » » for x := range U {
78 » » » » » T[x] ^= U[x] 67 » » » » T[x] ^= U[x]
79 » » » » }
80 } 68 }
81 // Derived key = T_1 || T_2 || ... || T_l
82 // N.B.: || means concatenation
83 DK = append(DK, T...)
84 } 69 }
85 » » return DK[:dkLen] 70 » » // Derived key = T_1 || T_2 || ... || T_l
71 » » dk = append(dk, T...)
86 } 72 }
73 return dk[:keylen]
87 } 74 }
LEFTRIGHT

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