DEV Community

Naman Tamrakar
Naman Tamrakar

Posted on

How to take hidden password from terminal in C/C++

Have you every wondered, In some terminal programs when they ask for password and you enter it, so either it does not display anything or displays '**********' while typing.

So how these programs take passwords?

The default input mode of terminal is echo, So as soon as we start typing any character in the terminal it show there simultaneously. But we can change this default behavior to do our job of taking the password from terminal without being it visible.

Here is a simple program that demonstrate how we can do this. termios.h is the header file where all the struct and function related to terminal are defined.

#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>

int getch() {
    int ch;
    // struct to hold the terminal settings
    struct termios old_settings, new_settings;
    // take default setting in old_settings
    tcgetattr(STDIN_FILENO, &old_settings);
    // make of copy of it (Read my previous blog to know 
    // more about how to copy struct)
    new_settings = old_settings;
    // change the settings for by disabling ECHO mode
    // read man page of termios.h for more settings info
    new_settings.c_lflag &= ~(ICANON | ECHO);
    // apply these new settings
    tcsetattr(STDIN_FILENO, TCSANOW, &new_settings);
    // now take the input in this mode
    ch = getchar();
    // reset back to default settings
    tcsetattr(STDIN_FILENO, TCSANOW, &old_settings);
    return ch;
}

int main(void) {
    char password[100];
    int i = 0;
    int ch;

    printf("Enter password: ");
    while ((ch = getch()) != '\n') {
        if (ch == 127 || ch == 8) { // handle backspace
            if (i != 0) {
                i--;
                printf("\b \b");
            }
        } else {
            password[i++] = ch;
            // echo the '*' to get feel of taking password 
            printf("*");
        }
    }
    password[i] = '\0';

    printf("\nYou entered password: %s\n", password);

    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Output:

Enter password: *****
You entered password: naman
Enter fullscreen mode Exit fullscreen mode

Instead of writing this whole program we can either use inbuild function getoass define in unistd.h header to take password without echoing but we don't get much control here like echoing '*' while writing.

#include <stdio.h>
#include <unistd.h>

int main(void) {
    char *password;

    password = getpass("Enter password: ");
    printf("You entered password: %s\n", password);

    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Output:

Enter password:
You entered password: naman
Enter fullscreen mode Exit fullscreen mode

NOTE: The man page of getpass says function opens /dev/tty (the controlling terminal of the process), outputs the string prompt, turns off echoing, reads one line (the "password"), restores the terminal state and closes /dev/tty again. which means that password will not be stored in the shell history.

NOTE: Custom implementation of this program also does not store the password in the shell history even though it is taking input from stdin. The reason is that the getch function reads a character directly from the terminal without waiting for the user to press the enter key, so the password is not passed to the shell as a command.

Thank you ❤️ so much for reading this article. I'm also a student learning new things so If you find any mistakes or have any suggestions please let me know in the comments.

Also, consider sharing and giving a thumbs up If this post helps you in any way.

Top comments (3)

Collapse
 
pauljlucas profile image
Paul J. Lucas

You shouldn't name the function getch() since there's already a curses library function with the same name.

Collapse
 
mrz2001 profile image
Mr.Z

It's ok in linux. linux does not have 'getch()' function.

Collapse
 
pauljlucas profile image
Paul J. Lucas

The point is to be cross-platform. Not everybody uses Linux.