github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/security/password.go (about) 1 // Copyright 2015 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package security 12 13 import ( 14 "crypto/sha256" 15 "fmt" 16 "os" 17 18 "github.com/cockroachdb/errors" 19 "golang.org/x/crypto/bcrypt" 20 "golang.org/x/crypto/ssh/terminal" 21 ) 22 23 // BcryptCost is the cost to use when hashing passwords. It is exposed for 24 // testing. 25 // 26 // BcryptCost should increase along with computation power. 27 // For estimates, see: http://security.stackexchange.com/questions/17207/recommended-of-rounds-for-bcrypt 28 // For now, we use the library's default cost. 29 var BcryptCost = bcrypt.DefaultCost 30 31 // ErrEmptyPassword indicates that an empty password was attempted to be set. 32 var ErrEmptyPassword = errors.New("empty passwords are not permitted") 33 34 var sha256NewSum = sha256.New().Sum(nil) 35 36 // TODO(mjibson): properly apply SHA-256 to the password. The current code 37 // erroneously appends the SHA-256 of the empty hash to the unhashed password 38 // instead of actually hashing the password. Fixing this requires a somewhat 39 // complicated backwards compatibility dance. This is not a security issue 40 // because the round of SHA-256 was only intended to achieve a fixed-length 41 // input to bcrypt; it is bcrypt that provides the cryptographic security, and 42 // bcrypt is correctly applied. 43 func appendEmptySha256(password string) []byte { 44 // In the past we incorrectly called the hash.Hash.Sum method. That 45 // method uses its argument as a place to put the current hash: 46 // it does not add its argument to the current hash. Thus, using 47 // h.Sum([]byte(password))) is the equivalent to the below append. 48 return append([]byte(password), sha256NewSum...) 49 } 50 51 // CompareHashAndPassword tests that the provided bytes are equivalent to the 52 // hash of the supplied password. If they are not equivalent, returns an 53 // error. 54 func CompareHashAndPassword(hashedPassword []byte, password string) error { 55 return bcrypt.CompareHashAndPassword(hashedPassword, appendEmptySha256(password)) 56 } 57 58 // HashPassword takes a raw password and returns a bcrypt hashed password. 59 func HashPassword(password string) ([]byte, error) { 60 return bcrypt.GenerateFromPassword(appendEmptySha256(password), BcryptCost) 61 } 62 63 // PromptForPassword prompts for a password. 64 // This is meant to be used when using a password. 65 func PromptForPassword() (string, error) { 66 fmt.Print("Enter password: ") 67 password, err := terminal.ReadPassword(int(os.Stdin.Fd())) 68 if err != nil { 69 return "", err 70 } 71 // Make sure stdout moves on to the next line. 72 fmt.Print("\n") 73 74 return string(password), nil 75 }