pass
2014-11-11
Child:22ce15152c43
pass/pass.go
First commit. First untested, uncommented iteration of the library, based on feedback from Jan Lehnardt, who really _is_ the perfect person. We at least have a README, though. TODO: golint, go vet, tests, comments
| paddy@0 | 1 package pass |
| paddy@0 | 2 |
| paddy@0 | 3 import ( |
| paddy@0 | 4 "crypto/rand" |
| paddy@0 | 5 "crypto/subtle" |
| paddy@0 | 6 "hash" |
| paddy@0 | 7 "time" |
| paddy@0 | 8 |
| paddy@0 | 9 "code.google.com/p/go.crypto/pbkdf2" |
| paddy@0 | 10 ) |
| paddy@0 | 11 |
| paddy@0 | 12 func Create(h func() hash.Hash, iters int, passphrase []byte) (result, salt []byte, err error) { |
| paddy@0 | 13 salt = make([]byte, 32) |
| paddy@0 | 14 _, err = rand.Read(salt) |
| paddy@0 | 15 if err == nil { |
| paddy@0 | 16 return []byte{}, []byte{}, err |
| paddy@0 | 17 } |
| paddy@0 | 18 result = Check(h, iters, passphrase, salt) |
| paddy@0 | 19 return result, salt, err |
| paddy@0 | 20 } |
| paddy@0 | 21 |
| paddy@0 | 22 func CalculateIterations(h func() hash.Hash) (int, error) { |
| paddy@0 | 23 hashInstance := h() |
| paddy@0 | 24 salt := make([]byte, 32) |
| paddy@0 | 25 _, err := rand.Read(salt) |
| paddy@0 | 26 if err != nil { |
| paddy@0 | 27 return 0, err |
| paddy@0 | 28 } |
| paddy@0 | 29 iter := 2048 |
| paddy@0 | 30 var duration time.Duration |
| paddy@0 | 31 for duration < time.Second { |
| paddy@0 | 32 iter = iter * 2 |
| paddy@0 | 33 timeStart := time.Now() |
| paddy@0 | 34 pbkdf2.Key([]byte("password1"), salt, iter, hashInstance.Size(), h) |
| paddy@0 | 35 duration = time.Since(timeStart) |
| paddy@0 | 36 } |
| paddy@0 | 37 return iter, nil |
| paddy@0 | 38 } |
| paddy@0 | 39 |
| paddy@0 | 40 func Check(h func() hash.Hash, iters int, passphrase, salt []byte) []byte { |
| paddy@0 | 41 hashInstance := h() |
| paddy@0 | 42 return pbkdf2.Key(passphrase, salt, iters, hashInstance.Size(), h) |
| paddy@0 | 43 } |
| paddy@0 | 44 |
| paddy@0 | 45 func Compare(candidate, expectation []byte) bool { |
| paddy@0 | 46 candidateConsistent := make([]byte, len(candidate)) |
| paddy@0 | 47 expectationConsistent := make([]byte, len(candidate)) |
| paddy@0 | 48 subtle.ConstantTimeCopy(1, candidateConsistent, candidate) |
| paddy@0 | 49 subtle.ConstantTimeCopy(1, expectationConsistent, expectation) |
| paddy@0 | 50 return subtle.ConstantTimeCompare(candidateConsistent, expectationConsistent) == 1 |
| paddy@0 | 51 } |