//go:build windows package main import ( "bufio" "fmt" "os" "strings" "syscall" "unsafe" ) // enableEchoInput is the Windows console mode bit that echoes typed input. const enableEchoInput = 0x0004 // promptPassword reads a password from the console with echo disabled, using // kernel32 directly so no third-party dependency is needed. If the console // mode cannot be changed (e.g. piped stdin), it falls back to an echoed read. func promptPassword(label string) (string, error) { fmt.Fprint(os.Stderr, label) kernel32 := syscall.NewLazyDLL("kernel32.dll") getConsoleMode := kernel32.NewProc("GetConsoleMode") setConsoleMode := kernel32.NewProc("SetConsoleMode") handle := syscall.Handle(os.Stdin.Fd()) var mode uint32 echoDisabled := false if r, _, _ := getConsoleMode.Call(uintptr(handle), uintptr(unsafe.Pointer(&mode))); r != 0 { if ret, _, _ := setConsoleMode.Call(uintptr(handle), uintptr(mode&^enableEchoInput)); ret != 0 { echoDisabled = true defer setConsoleMode.Call(uintptr(handle), uintptr(mode)) } } line, err := bufio.NewReader(os.Stdin).ReadString('\n') if echoDisabled { fmt.Fprintln(os.Stderr) // the Enter keystroke was not echoed } if err != nil && line == "" { return "", fmt.Errorf("read password: %w", err) } return strings.TrimRight(line, "\r\n"), nil }