decred.org/dcrdex@v1.0.5/server/admin/prompt.go (about) 1 // This code is available on the terms of the project LICENSE.md file, 2 // also available online at https://blueoakcouncil.org/license/1.0.0. 3 4 package admin 5 6 import ( 7 "context" 8 "crypto/sha256" 9 "fmt" 10 "os" 11 12 "decred.org/dcrdex/dex/encode" 13 "golang.org/x/term" 14 ) 15 16 type passwordReadResponse struct { 17 password []byte 18 err error 19 } 20 21 // PasswordPrompt prompts the user to enter a password. Password must not be an 22 // empty string. 23 func PasswordPrompt(ctx context.Context, prompt string) ([]byte, error) { 24 // Get the initial state of the terminal. 25 initialTermState, err := term.GetState(int(os.Stdin.Fd())) 26 if err != nil { 27 return nil, err 28 } 29 30 passwordReadChan := make(chan passwordReadResponse, 1) 31 32 go func() { 33 fmt.Print(prompt) 34 pass, err := term.ReadPassword(int(os.Stdin.Fd())) 35 fmt.Println() 36 passwordReadChan <- passwordReadResponse{ 37 password: pass, 38 err: err, 39 } 40 }() 41 42 select { 43 case <-ctx.Done(): 44 _ = term.Restore(int(os.Stdin.Fd()), initialTermState) 45 return nil, ctx.Err() 46 47 case res := <-passwordReadChan: 48 if res.err != nil { 49 return nil, res.err 50 } 51 return res.password, nil 52 } 53 } 54 55 // PasswordHashPrompt prompts the user to enter a password and returns its 56 // SHA256 hash. Password must not be an empty string. 57 func PasswordHashPrompt(ctx context.Context, prompt string) ([sha256.Size]byte, error) { 58 var authSHA [sha256.Size]byte 59 passBytes, err := PasswordPrompt(ctx, prompt) 60 if err != nil { 61 return authSHA, err 62 } 63 authSHA = sha256.Sum256(passBytes) 64 // Zero password bytes. 65 encode.ClearBytes(passBytes) 66 return authSHA, nil 67 }