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?
There are various Python modules that are used to hide the user's inputted password, among them one is maskpass() module. In Python with the help of maskpass() module and base64() module we can hide the password of users with asterisk(*) during input time and then with the help of base64() module it can be encrypted.
The getpass() function first disables echoing and all processing of terminal special characters (such as the interrupt character, normally Control-C).
Use getch() to get the input instead of using cin , so the input will not be shown (quoting wiki): int getch(void) Reads a character directly from the console without buffer, and without echo.
Use either key shortcut: Esc , #
In the Linux world, masking isn't usually done with asterisks, normally echoing is just turned off and the terminal displays blanks E.g. if you use su
or log into a virtual terminal etc.
There is a library function to handle getting passwords, it won't mask the password with asterisks but will disable echoing of the password to terminal. I pulled this out of a linux book I have. I believe its part of the posix standard
#include <unistd.h> char *getpass(const char *prompt); /*Returns pointer to statically allocated input password string on success, or NULL on error*/
The getpass() function first disables echoing and all processing of terminal special characters (such as the interrupt character, normally Control-C).
It then prints the string pointed to by prompt, and reads a line of input, returning the null-terminated input string with the trailing newline stripped, as its function result.
A google search for getpass() has a reference to the GNU implementation (should be in most linux distros) and some sample code for implementing your own if need be
http://www.gnu.org/s/hello/manual/libc/getpass.html
Their example for rolling your own:
#include <termios.h> #include <stdio.h> ssize_t my_getpass (char **lineptr, size_t *n, FILE *stream) { struct termios old, new; int nread; /* Turn echoing off and fail if we can't. */ if (tcgetattr (fileno (stream), &old) != 0) return -1; new = old; new.c_lflag &= ~ECHO; if (tcsetattr (fileno (stream), TCSAFLUSH, &new) != 0) return -1; /* Read the password. */ nread = getline (lineptr, n, stream); /* Restore terminal. */ (void) tcsetattr (fileno (stream), TCSAFLUSH, &old); return nread; }
If need be you could use this as the basis as modify it to display asterisks.
Without getch
to rely on and avoiding the obsolete getpass
, the recommended approach is to disable terminal ECHO through termios
use. After a few searches to find a canned flexible password routine, I was surprised that very few for stand-alone use with C. Rather than simply recoding getch
with termios c_lflag
options, slightly more generalized approach takes just a few additions. Beyond replacing getch
any routine should enforce a specified maximum length to prevent overflow, truncate if the user attempt to enter beyond the maximum, and warn if truncation occurs in some manner.
Below, the additions will allow reading from any FILE *
input stream, limiting the length to a specified length, provide minimal editing (backspace) ability when taking input, allow the character mask to be specified or disabled completely, and finally return the length of the password entered. A warning was added when the password entered was truncated to the maximum or specified length.
Hopefully it will prove useful to others with this question looking for a similar solution:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <termios.h> #define MAXPW 32 /* read a string from fp into pw masking keypress with mask char. getpasswd will read upto sz - 1 chars into pw, null-terminating the resulting string. On success, the number of characters in pw are returned, -1 otherwise. */ ssize_t getpasswd (char **pw, size_t sz, int mask, FILE *fp) { if (!pw || !sz || !fp) return -1; /* validate input */ #ifdef MAXPW if (sz > MAXPW) sz = MAXPW; #endif if (*pw == NULL) { /* reallocate if no address */ void *tmp = realloc (*pw, sz * sizeof **pw); if (!tmp) return -1; memset (tmp, 0, sz); /* initialize memory to 0 */ *pw = (char*) tmp; } size_t idx = 0; /* index, number of chars in read */ int c = 0; struct termios old_kbd_mode; /* orig keyboard settings */ struct termios new_kbd_mode; if (tcgetattr (0, &old_kbd_mode)) { /* save orig settings */ fprintf (stderr, "%s() error: tcgetattr failed.\n", __func__); return -1; } /* copy old to new */ memcpy (&new_kbd_mode, &old_kbd_mode, sizeof(struct termios)); new_kbd_mode.c_lflag &= ~(ICANON | ECHO); /* new kbd flags */ new_kbd_mode.c_cc[VTIME] = 0; new_kbd_mode.c_cc[VMIN] = 1; if (tcsetattr (0, TCSANOW, &new_kbd_mode)) { fprintf (stderr, "%s() error: tcsetattr failed.\n", __func__); return -1; } /* read chars from fp, mask if valid char specified */ while (((c = fgetc (fp)) != '\n' && c != EOF && idx < sz - 1) || (idx == sz - 1 && c == 127)) { if (c != 127) { if (31 < mask && mask < 127) /* valid ascii char */ fputc (mask, stdout); (*pw)[idx++] = c; } else if (idx > 0) { /* handle backspace (del) */ if (31 < mask && mask < 127) { fputc (0x8, stdout); fputc (' ', stdout); fputc (0x8, stdout); } (*pw)[--idx] = 0; } } (*pw)[idx] = 0; /* null-terminate */ /* reset original keyboard */ if (tcsetattr (0, TCSANOW, &old_kbd_mode)) { fprintf (stderr, "%s() error: tcsetattr failed.\n", __func__); return -1; } if (idx == sz - 1 && c != '\n') /* warn if pw truncated */ fprintf (stderr, " (%s() warning: truncated at %zu chars.)\n", __func__, sz - 1); return idx; /* number of chars in passwd */ }
A simple program showing the use would be as follows. If using a static array of character for holding the password, just insure a pointer is passed to the function.
int main (void ) { char pw[MAXPW] = {0}; char *p = pw; FILE *fp = stdin; ssize_t nchr = 0; printf ( "\n Enter password: "); nchr = getpasswd (&p, MAXPW, '*', fp); printf ("\n you entered : %s (%zu chars)\n", p, nchr); printf ( "\n Enter password: "); nchr = getpasswd (&p, MAXPW, 0, fp); printf ("\n you entered : %s (%zu chars)\n\n", p, nchr); return 0; }
Example Output
$ ./bin/getpasswd2 Enter password: ****** you entered : 123456 (6 chars) Enter password: you entered : abcdef (6 chars)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With