Published by
Nov 7, 2009 (last update: Jan 29, 2012)

Masking password input

Score: 3.9/5 (50 votes)
*****

Contents



Unix/Linux

Example 1


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;

int getch() {
    int ch;
    struct termios t_old, t_new;

    tcgetattr(STDIN_FILENO, &t_old);
    t_new = t_old;
    t_new.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &t_new);

    ch = getchar();

    tcsetattr(STDIN_FILENO, TCSANOW, &t_old);
    return ch;
}





string getpass(const char *prompt, bool show_asterisk=true)
{
  const char BACKSPACE=127;
  const char RETURN=10;

  string password;
  unsigned char ch=0;

  cout <<prompt<<endl;

  while((ch=getch())!=RETURN)
    {
       if(ch==BACKSPACE)
         {
            if(password.length()!=0)
              {
                 if(show_asterisk)
                 cout <<"\b \b";
                 password.resize(password.length()-1);
              }
         }
       else
         {
             password+=ch;
             if(show_asterisk)
                 cout <<'*';
         }
    }
  cout <<endl;
  return password;
}


int main()
{
  const char *correct_password="null";

  string password=getpass("Please enter the password: ",true); // Show asterisks
  if(password==correct_password)
      cout <<"Correct password"<<endl;
  else
      cout <<"Incorrect password. Try again"<<endl;


  password=getpass("Please enter the password: ",false); // Do not show asterisks
  if(password==correct_password)
      cout <<"Correct password"<<endl;
  else
      cout <<"Incorrect password. Try again"<<endl;

  return 0;
}


Example 2 - using getpass() function

According to the Linux programmers's manual, this function is obsolete, so avoid it when possible.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <cstdlib>
#include <iostream>
using namespace std;

const char *mypass="null";

int main()
{
char *password=getpass("Enter password: ");

if(strcmp(password,mypass)==0) cout <<"Correct password!\n";
else cout <<"Incorrect password!\n";


return 0;
}






Windows

Example 1 - using WinAPI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <iostream>
#include <string>
#include <windows.h>
using namespace std;


string getpass(const char *prompt, bool show_asterisk=true)
{
  const char BACKSPACE=8;
  const char RETURN=13;

  string password;
  unsigned char ch=0;

  cout <<prompt<<endl;

  DWORD con_mode;
  DWORD dwRead;

  HANDLE hIn=GetStdHandle(STD_INPUT_HANDLE);

  GetConsoleMode( hIn, &con_mode );
  SetConsoleMode( hIn, con_mode & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT) );

  while(ReadConsoleA( hIn, &ch, 1, &dwRead, NULL) && ch !=RETURN)
    {
       if(ch==BACKSPACE)
         {
            if(password.length()!=0)
              {
                 if(show_asterisk)
                     cout <<"\b \b";
                 password.resize(password.length()-1);
              }
         }
       else
         {
             password+=ch;
             if(show_asterisk)
                 cout <<'*';
         }
    }
  cout <<endl;
  return password;
}



int main()
{
  const char *correct_password="null";

  cout <<"Test 1: echoing enabled"<<endl;
  string password=getpass("Please enter the password: ",true); // Show asterisks
  if(password==correct_password)
      cout <<"Correct password"<<endl;
  else
      cout <<"Incorrect password. Try again"<<endl;

  cout <<"\nTest 2: echoing disabled"<<endl;
  password=getpass("Please enter the password: ",false); // Do not show asterisks
  if(password==correct_password)
      cout <<"Correct password"<<endl;
  else
      cout <<"Incorrect password. Try again"<<endl;

  return 0;
}





Example 2 - using conio.h

This code is analogous to the previous example but uses getch() function from conio.h header to get unbuffered console input. Note that conio.h is a Borland-specific header, so avoid it when possible.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;


string getpass(const char *prompt, bool show_asterisk=true)
{
  const char BACKSPACE=8;
  const char RETURN=13;

  string password;
  unsigned char ch=0;

  cout <<prompt<<endl;

  while((ch=getch())!=RETURN)
    {
       if(ch==BACKSPACE)
         {
            if(password.length()!=0)
              {
                 if(show_asterisk)
                 cout <<"\b \b";
                 password.resize(password.length()-1);
              }
         }
       else if(ch==0 || ch==224) // handle escape sequences
         {
             getch(); // ignore non printable chars
             continue;
         }
       else
         {
             password+=ch;
             if(show_asterisk)
                 cout <<'*';
         }
    }
  cout <<endl;
  return password;
}


int main()
{
  const char *correct_password="null";

  string password=getpass("Please enter the password: ",true); // Show asterisks
  if(password==correct_password)
      cout <<"Correct password"<<endl;
  else
      cout <<"Incorrect password. Try again"<<endl;


  password=getpass("Please enter the password: ",false); // Do not show asterisks
  if(password==correct_password)
      cout <<"Correct password"<<endl;
  else
      cout <<"Incorrect password. Try again"<<endl;

  return 0;
}

Note that if the password is longer that the console width (80 characters) backspace will not delete asterisks from the previous line.





Using curses library

Curses library is one of the best choices for cross-platform console manipulation. Keep in mind that this library has been designed for C programming language, so you won't be able to use C++ iostream's with it.


Example 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <string>
#include <curses.h>
using namespace std;


string getpass(const char *prompt)
{
  printw(prompt);
  noecho();  // disable character echoing

  char buff[64];
  getnstr(buff,sizeof(buff));

  echo(); // enable character echoing again
  return buff;
}

int main()
{
   const string correct_password="null";

   initscr(); // enable ncurses

   string pwd=getpass("Please enter the password: ");

   if(correct_password==pwd)
       printw("\nCorrect password!");
   else
       printw("\nIncorrect password. Try again");


    getch(); // Wait for a keypress
    endwin(); // disable ncurses

    return 0;
}


Example 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <string>
#include <curses.h>
using namespace std;


string getpass(const char *prompt, bool show_asterisk=true)
{
  const char BACKSPACE=8;
  const char RETURN=10; // Note: 10 for curses, 13 for conio

  string password;
  unsigned char ch=0;

  printw(prompt);
  printw("\n");

  noecho(); // Disable echoing

  while((ch=getch())!=RETURN)
    {
       if(ch==BACKSPACE)
         {
            if(password.length()!=0)
              {
                 if(show_asterisk)
                 printw("\b \b");
                 password.resize(password.length()-1);
              }
         }
       else if(ch!=27) // ignore 'escape' key
         {
             password+=ch;
             if(show_asterisk)
                 printw("*");
         }
    }

  echo();
  printw("\n");
  return password;
}





int main()
{
  initscr();

  const char *correct_password="null";

  printw("Test 1: echoing enabled\n");
  string password=getpass("Please enter the password: ",true); // Show asterisks
  if(password==correct_password)
      printw("Correct password!\n");
  else
      printw("Incorrect password. Try again\n");

  printw("\nTest 2: echoing disabled\n");
  password=getpass("Please enter the password: ",false); // Do not show asterisks
  if(password==correct_password)
      printw("Correct password");
  else
      printw("Incorrect password. Try again");

  printw("\n\nPress any key to continue...");
  getch();
  endwin();
  return 0;
}


Notes:
1. Download curses here:
http://sourceforge.net/projects/pdcurses/files/
2. You must link your project with pdcurses.lib library.