Hide password input on terminal

Viewed 100420

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

#include <conio.h>   
int main()
{
    char c,password[10];
    int i;
    while( (c=getch())!= '\n');{
        password[i] = c;
        printf("*");
        i++;
    }
    return 1;
}

but the problem is that GCC does not include conio.h file so, getch() is useless for me. Does anyone have a solution?

16 Answers

Just pass for it the char* that you want to set password in and its size and the function will do its job

void set_Password(char *get_in, int sz){
    for (int i = 0; i < sz;) {
        char ch = getch();
        if (ch == 13) {
            get_in[i] = '\0';
            break;
        }
        else if(ch != 8){
            get_in[i++] = ch;
            putch('*');
        }
        else if(i > 0)
            cout << "\b \b",get_in[i--] = '\0';
    }
    cout << "\n";
}

This is an example, run it on your compiler

man getpass

This function is obsolete. Do not use it. If you want to read input without terminal echoing enabled, see the description of the ECHO flag in termios(3)

# include <termios.h>
# include <unistd.h>   /* needed for STDIN_FILENO which is an int file descriptor */

struct termios tp, save;

tcgetattr( STDIN_FILENO, &tp);              /* get existing terminal properties */
save = tp;                                  /* save existing terminal properties */

tp.c_lflag &= ~ECHO;                        /* only cause terminal echo off */

tcsetattr( STDIN_FILENO, TCSAFLUSH, &tp );  /* set terminal settings */

/*
   now input by user in terminal will not be displayed
   and cursor will not move
*/

tcsetattr( STDIN_FILENO, TCSANOW, &save);   /* restore original terminal settings */

If you notice, most current linux distro's do not mask a password with asterisks. Doing so divulges the length of the password which is no way beneficial. It is easier and better to simply make the cursor not move when a password is typed in. If for whatever reason you require a * to be printed for every character that's typed then you would have to grab every keypress before Enter is hit and that's always been problematic.

printf("\nENTER PASSWORD: ");
while (1)
{
    ch=getch();
    if(ch==13)    //ON ENTER PRESS
        break;

    else if(ch==8)    //ON BACKSPACE PRESS REMOVES CHARACTER
    {
        if(i>0)
        {
            i--;
            password[i]='\0';
            printf("\b \b");
        }
    }
    else if (ch==32 || ch==9)    //ON PRESSING TAB OR SPACE KEY
        continue;
    else
    {
        password[i]=ch;
        i++;
        printf("*");
    }         
}
password[i]='\0';

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.

Related