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
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/pass.go Tue Nov 11 19:26:25 2014 -0500 1.3 @@ -0,0 +1,51 @@ 1.4 +package pass 1.5 + 1.6 +import ( 1.7 + "crypto/rand" 1.8 + "crypto/subtle" 1.9 + "hash" 1.10 + "time" 1.11 + 1.12 + "code.google.com/p/go.crypto/pbkdf2" 1.13 +) 1.14 + 1.15 +func Create(h func() hash.Hash, iters int, passphrase []byte) (result, salt []byte, err error) { 1.16 + salt = make([]byte, 32) 1.17 + _, err = rand.Read(salt) 1.18 + if err == nil { 1.19 + return []byte{}, []byte{}, err 1.20 + } 1.21 + result = Check(h, iters, passphrase, salt) 1.22 + return result, salt, err 1.23 +} 1.24 + 1.25 +func CalculateIterations(h func() hash.Hash) (int, error) { 1.26 + hashInstance := h() 1.27 + salt := make([]byte, 32) 1.28 + _, err := rand.Read(salt) 1.29 + if err != nil { 1.30 + return 0, err 1.31 + } 1.32 + iter := 2048 1.33 + var duration time.Duration 1.34 + for duration < time.Second { 1.35 + iter = iter * 2 1.36 + timeStart := time.Now() 1.37 + pbkdf2.Key([]byte("password1"), salt, iter, hashInstance.Size(), h) 1.38 + duration = time.Since(timeStart) 1.39 + } 1.40 + return iter, nil 1.41 +} 1.42 + 1.43 +func Check(h func() hash.Hash, iters int, passphrase, salt []byte) []byte { 1.44 + hashInstance := h() 1.45 + return pbkdf2.Key(passphrase, salt, iters, hashInstance.Size(), h) 1.46 +} 1.47 + 1.48 +func Compare(candidate, expectation []byte) bool { 1.49 + candidateConsistent := make([]byte, len(candidate)) 1.50 + expectationConsistent := make([]byte, len(candidate)) 1.51 + subtle.ConstantTimeCopy(1, candidateConsistent, candidate) 1.52 + subtle.ConstantTimeCopy(1, expectationConsistent, expectation) 1.53 + return subtle.ConstantTimeCompare(candidateConsistent, expectationConsistent) == 1 1.54 +}