Masking password input
Unix/Linux
Example 1
#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.
#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
#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.
#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
#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
#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.