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  }