Hide password input on terminal

后端 未结 15 1327
清酒与你
清酒与你 2020-11-22 09:55

I want to mask my password while writing it with *. I use Linux GCC for this code. I know one solution is to use getch() function like this

相关标签:
15条回答
  • 2020-11-22 10:25

    Thanks all of you whose help & support to solve my problem. I find a best way to hide my password in linux that fits me best. To use getpass() function. It just need to include "unistd.h" file.

    syntex of getpass function:

    char * getpass (const char *prompt)

    Parameters: prompt: string pointer to print while asking for Password

    Return Value: string pointer of password

    Example:

    #include <stdio.h>
    #include <unistd.h>   
    int main()
    {
        char *password; // password string pointer
        password = getpass("Enter Password: "); // get a password
        printf("%s\n",password); // this is just for conformation
                                 // that password stored successfully
        return 1;
    }
    

    output:

    Enter Password:

    heet

    0 讨论(0)
  • 2020-11-22 10:29

    The functionality of getch (which is a non-standard, Windows function) can be emulated with this code:

    #include <termios.h>
    #include <unistd.h>
    int getch() {
        struct termios oldt, newt;
        int ch;
        tcgetattr(STDIN_FILENO, &oldt);
        newt = oldt;
        newt.c_lflag &= ~(ICANON | ECHO);
        tcsetattr(STDIN_FILENO, TCSANOW, &newt);
        ch = getchar();
        tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
        return ch;
    }
    

    Note that your approach is not perfect - it's better to use something like ncurses or another terminal library to handle these things.

    0 讨论(0)
  • 2020-11-22 10:29

    With scanning the characters you can take it into a buffer. Also you need to write code if backspace is pressed, and appropriately correct the inserted password.

    Here is a code which once i wrote with the curses. Compile with gcc file.c -o pass_prog -lcurses

    #include <stdio.h>
    #include <stdlib.h>
    #include <curses.h>
    
    #define ENOUGH_SIZE 256
    
    #define ECHO_ON 1
    #define ECHO_OFF 0
    
    #define BACK_SPACE 127
    
    char *my_getpass (int echo_state);
    
    int main (void)
    {
      char *pass;
    
      initscr ();
    
      printw ("Enter Password: ");
      pass = my_getpass (ECHO_ON);
    
      printw ("\nEntered Password: %s", pass);
      refresh ();
      getch ();
      endwin ();
      return 0;
    }
    
    
    char *my_getpass (int echo_state)
    {
      char *pass, c;
      int i=0;
    
      pass = malloc (sizeof (char) * ENOUGH_SIZE);
      if (pass == NULL)
      {
        perror ("Exit");
        exit (1);
      }
    
      cbreak ();
      noecho ();
    
      while ((c=getch()) != '\n')
      {
        if (c == BACK_SPACE)
        {
          /* Do not let the buffer underflow */
          if (i > 0)
          { 
            i--;
            if (echo_state == ECHO_ON)
                   printw ("\b \b");
          }
        }
        else if (c == '\t')
          ; /* Ignore tabs */
        else
        {
          pass[i] = c;
          i = (i >= ENOUGH_SIZE) ? ENOUGH_SIZE - 1 : i+1;
          if (echo_state == ECHO_ON)
            printw ("*");
        }
      }
      echo ();
      nocbreak ();
      /* Terminate the password string with NUL */
      pass[i] = '\0';
      endwin ();
      return pass;
    }
    
    0 讨论(0)
  • 2020-11-22 10:30

    Here is my idea, adapted from that of the C++ official site.

    #include <termios.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <iostream>
    #include <string>
    using namespace std;
    string getpass(const char *prompt, bool showchar = false, char echochar = '*')
    {
        struct termios oi, ni;
        tcgetattr(STDIN_FILENO, &oi);
        ni = oi;
        ni.c_lflag &= ~(ICANON | ECHO);
        const char DELETE = 127;
        const char RETURN = 10;
        string password;
        unsigned char ch = 0;
        cout << prompt;
        tcsetattr(STDIN_FILENO, TCSANOW, &ni);
        while (getchar() != RETURN) {
            if (ch == DELETE) {
                if(password.length != 0){
                    if (showchar) cout << "\b \b";
                    password.resize(password.length() - 1);
                }
            }else {
                password += getchar();
                if (showchar) cout << echochar;
            }
        }
        tcsetattr(STDIN_FILENO,TCSANOW,&oi)
        cout << endl;
        return password;
    }
    

    It will read one character at once and add it to the string and supports showing another character.

    0 讨论(0)
  • 2020-11-22 10:33

    Your method is correct, however you'll need to turn off terminal echo while the password is being entered:

    #include <sgtty.h>
    
    void echo_off()
    {
        struct sgttyb state;
        (void)ioctl(0, (int)TIOCGETP, (char *)&state);
        state.sg_flags &= ~ECHO;
        (void)ioctl(0, (int)TIOCSETP, (char *)&state);
    }
    
    void echo_on()
    {
        struct sgttyb state;
        (void)ioctl(0, (int)TIOCGETP, (char *)&state);
        state.sg_flags |= ECHO;
        (void)ioctl(0, (int)TIOCSETP, (char *)&state);
    }
    

    Instead of getch(), why not just use getc() instead?

    0 讨论(0)
  • 2020-11-22 10:33

    Unfortunately in the C standard library there is no such function out of the box. Maybe in third party library.

    One option is use ANSI escape sequences to set the background color to foreground color in the console to conceal the password. Try this link.

    0 讨论(0)
提交回复
热议问题