Masquer la saisie du mot de passe sur le terminal

Je veux masquer mon mot de passe en l’écrivant avec * . J’utilise Linux GCC pour ce code. Je sais qu’une solution consiste à utiliser la fonction getch() comme ceci

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

mais le problème est que GCC n’inclut pas le fichier conio.h donc, getch() est inutile pour moi. Quelqu’un a-t-il une solution?

Dans le monde Linux, le masquage ne se fait généralement pas avec des astérisques, l’écho est normalement désactivé et le terminal affiche des blancs. Par exemple, si vous utilisez su ou connectez-vous à un terminal virtuel, etc.

Il y a une fonction de bibliothèque pour gérer l’obtention des mots de passe, elle ne masquera pas le mot de passe avec des astérisques mais désactivera l’écho du mot de passe au terminal. Je l’ai sorti d’un livre Linux que j’ai. Je crois sa partie de la norme posix

 #include  char *getpass(const char *prompt); /*Returns pointer to statically allocated input password ssortingng on success, or NULL on error*/ 

La fonction getpass () désactive d’abord l’écho et tous les traitements des caractères spéciaux du terminal (tels que le caractère d’interruption, normalement Control-C).

Il imprime ensuite la chaîne pointée par l’invite et lit une ligne d’entrée, renvoyant la chaîne d’entrée terminée par un caractère nul avec le nouveau trait final supprimé, comme résultat de la fonction.

Une recherche sur Google pour getpass () a une référence à l’implémentation de GNU (devrait être dans la plupart des dissortingbutions linux) et un exemple de code pour implémenter votre propre si nécessaire

http://www.gnu.org/s/hello/manual/libc/getpass.html

Leur exemple pour rouler le vôtre:

 #include  #include  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; } 

Si nécessaire, vous pouvez l’utiliser comme base pour la modifier pour afficher des astérisques.

La fonctionnalité de getch (qui est une fonction Windows non standard) peut être émulée avec ce code:

 #include  #include  int getch() { struct termios oldt, newt; int ch; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newt); ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); return ch; } 

Notez que votre approche n’est pas parfaite – il est préférable d’utiliser quelque chose comme ncurses ou une autre bibliothèque de terminaux pour gérer ces choses.

Sans getch à getch et en évitant le getpass obsolète, il est recommandé de désactiver le terminal ECHO via termios . Après quelques recherches pour trouver une routine de mot de passe flexible, j’ai été surpris de constater que très peu d’applications autonomes avec C. Plutôt que de simplement recoder le getch avec les options de termios c_lflag , une approche légèrement plus généralisée ne nécessite que quelques ajouts. Au-delà du remplacement de getch toute routine doit imposer une longueur maximale spécifiée pour éviter le dépassement de capacité, tronquer si l’utilisateur tente d’entrer au-delà du maximum et avertir si une troncature se produit d’une manière ou d’une autre.

Ci-dessous, les ajouts permettront de lire n’importe quel stream d’entrée FILE * , en limitant la longueur à une longueur spécifiée, de fournir une modification minimale (retour arrière) en entrée, de spécifier ou de désactiver complètement le masque de caractères et de le mot de passe entré Un avertissement a été ajouté lorsque le mot de passe entré a été tronqué à la longueur maximale ou spécifiée.

Espérons que cela se révélera utile pour ceux qui ont cette question en cherchant une solution similaire:

 #include  #include  #include  #include  #include  #include  /* for errno */ #include  /* for EINTR */ #define MAXPW 32 /* read a ssortingng from fp into pw masking keypress with mask char. getpasswd will read upto sz - 1 chars into pw, null-terminating the resulting ssortingng. 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 = 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 */ } 

Un programme simple montrant l'utilisation serait comme suit. Si vous utilisez un tableau de caractères statique pour contenir le mot de passe, assurez-vous simplement qu'un pointeur est transmis à la fonction.

 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; } 

Exemple de sortie

 $ ./bin/getpasswd2 Enter password: ****** you entered : 123456 (6 chars) Enter password: you entered : abcdef (6 chars) 

Vous pouvez créer votre propre fonction getch() sous Linux de cette manière.

 int getch() { struct termios oldtc, newtc; int ch; tcgetattr(STDIN_FILENO, &oldtc); newtc = oldtc; newtc.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newtc); ch=getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldtc); return ch; } 

Code de démonstration:

 int main(int argc, char **argv) { int ch; printf("Press x to exit.\n\n"); for (;;) { ch = getch(); printf("ch = %c (%d)\n", ch, ch); if(ch == 'x') break; } return 0; } 

Votre méthode est correcte, mais vous devrez désactiver l’écho du terminal lorsque le mot de passe est entré:

 #include  void echo_off() { struct sgttyb state; (void)ioctl(0, (int)TIOCGETP, (char *)&state); state.sg_flags &= ~ECHO; (void)ioctl(0, (int)TIOCSETP, (char *)&state); } void echo_on() { struct sgttyb state; (void)ioctl(0, (int)TIOCGETP, (char *)&state); state.sg_flags |= ECHO; (void)ioctl(0, (int)TIOCSETP, (char *)&state); } 

Au lieu de getch() , pourquoi ne pas utiliser getc() place?

Merci à vous tous pour l’aide et le soutien dont vous avez besoin pour résoudre mon problème. Je trouve le meilleur moyen de cacher mon mot de passe sous Linux qui me convient le mieux. Pour utiliser la fonction getpass () Il suffit d’inclure le fichier “unistd.h”.

syntex de la fonction getpass:

char * getpass (invite de caractère const *)

Paramètres: invite: pointeur de chaîne à imprimer en demandant le mot de passe

Valeur de retour: pointeur de chaîne du mot de passe

Exemple:

 #include  #include  int main() { char *password; // password ssortingng pointer password = getpass("Enter Password: "); // get a password printf("%s\n",password); // this is just for conformation // that password stored successfully return 1; } 

sortie:

Entrer le mot de passe:

heet

Vous pouvez utiliser ncurses.h s’il n’est pas nécessaire d’être portable sur Windows, mais voici une version plus “portable”:

S’il n’est pas nécessaire d’être portable, pointez-vous sur une solution ncurses

portablegetch.h

 /*portablegetch.h*/ #ifndef PGETCH #define PGETCH #ifdef __unix__ #include  #include  static struct termios n_term; static struct termios o_term; static int cbreak(int fd) { if((tcgetattr(fd, &o_term)) == -1) return -1; n_term = o_term; n_term.c_lflag = n_term.c_lflag & ~(ECHO|ICANON); n_term.c_cc[VMIN] = 1; n_term.c_cc[VTIME]= 0; if((tcsetattr(fd, TCSAFLUSH, &n_term)) == -1) return -1; return 1; } int getch() { int cinput; if(cbreak(STDIN_FILENO) == -1) { fprintf(stderr, "cbreak failure, exiting \n"); exit(EXIT_FAILURE); } cinput = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &o_term); return cinput; } #elif _MSC_VER || __WIN32__ || __MS_DOS__ #include  #endif #endif 

Et le fichier c

quelque chose.c

 #include  #include  #include "portablegetch.h" int main(int argc, char **argv) { int input; printf("Please Enter your Password:\t"); while(( input=getch() ) != '\n') printf("*"); printf("\n"); return EXIT_SUCCESS; } 

Cela devrait correspondre à votre problème.

J’espère que cela pourra aider.

 #include  #include  static struct termios old, new; void initTermios(int echo) { tcgetattr(0, &old); new = old; new.c_lflag &= ~ICANON; new.c_lflag &= echo ? ECHO : ~ECHO; tcsetattr(0, TCSANOW, &new); } void resetTermios(void) { tcsetattr(0, TCSANOW, &old); } char getch_(int echo) { char ch; initTermios(echo); ch = getchar(); resetTermios(); return ch; } char getch(void) { return getch_(0); } int main(void) { char c; printf("(getch example) please type a letter..."); c = getch(); printf("\nYou typed: %c\n", c); return 0; } 

Il suffit de copier ces extraits et de les utiliser. J’espère que ça a aidé

Malheureusement, dans la bibliothèque standard C, aucune fonction de ce type n’est disponible. Peut-être dans une bibliothèque tierce.

Une option consiste à utiliser des séquences d’échappement ANSI pour définir la couleur d’arrière-plan sur la couleur de premier plan dans la console pour masquer le mot de passe. Essayez ce lien .

En scannant les caractères, vous pouvez le prendre dans un tampon. Vous devez également écrire du code si vous appuyez sur la touche Retour arrière et corriger correctement le mot de passe inséré.

Voici un code que j’ai écrit une fois avec les malédictions. Comstackr avec gcc file.c -o pass_prog -lcurses

 #include  #include  #include  #define ENOUGH_SIZE 256 #define ECHO_ON 1 #define ECHO_OFF 0 #define BACK_SPACE 127 char *my_getpass (int echo_state); int main (void) { char *pass; initscr (); printw ("Enter Password: "); pass = my_getpass (ECHO_ON); printw ("\nEntered Password: %s", pass); refresh (); getch (); endwin (); return 0; } char *my_getpass (int echo_state) { char *pass, c; int i=0; pass = malloc (sizeof (char) * ENOUGH_SIZE); if (pass == NULL) { perror ("Exit"); exit (1); } cbreak (); noecho (); while ((c=getch()) != '\n') { if (c == BACK_SPACE) { /* Do not let the buffer underflow */ if (i > 0) { i--; if (echo_state == ECHO_ON) printw ("\b \b"); } } else if (c == '\t') ; /* Ignore tabs */ else { pass[i] = c; i = (i >= ENOUGH_SIZE) ? ENOUGH_SIZE - 1 : i+1; if (echo_state == ECHO_ON) printw ("*"); } } echo (); nocbreak (); /* Terminate the password ssortingng with NUL */ pass[i] = '\0'; endwin (); return pass; } 

En C, vous pouvez utiliser la fonction getpasswd() qui fait à peu près la même chose que stty en shell, exemple:

 #include  #include  #include  #include  int main() { char acct[80], password[80]; printf(“Account: “); fgets(acct, 80, stdin); acct[strlen(acct)-1] = 0; /* remove carriage return */ strncpy(password, getpass(“Password: “), 80); printf(“You entered acct %s and pass %s\n”, acct, password); return 0; } 

Voici un script shell équivalent qui utilise stty (qui modifie les parameters de votre tty ):

 save_state=$(stty -g) /bin/echo -n “Account: “ read acct /bin/echo -n “Password: “ stty -echo read password # this won't echo stty “$save_state” echo “” echo account = $acct and password = $password 

Source: Comment lire un mot de passe sans le faire écho en C?

notez que les termios ICANON lflag désactivent le traitement carriagereturn / linefeed, et le paramètre ECHO termios désactive l’écho pour STDIN.

Lorsque vous utilisez ceci (avec ou sans écho activé) pour lire un mot de passe et imprimer '*' pour les caractères entrés, il ne s’agit pas seulement de lire les caractères jusqu’à ce qu’un retour à la ligne / chariot soit rencontré. ‘routine de construction de chaînes’ (sinon les espaces arrière se retrouvent dans la chaîne réelle, et ne provoquent pas la suppression de caractères comme ce serait le cas avec les différentes fonctions de saisie basées sur des chaînes).

la même chose arriverait en C sous DOS avec getch tho. cela renverrait également heureusement 0x08 pour backspace (ou 127 ou tout ce que votre os spécifique utilise comme backspace)

garder la trace de «ne pas supprimer – avant le début de la chaîne», remplacer la «nouvelle extrémité de la chaîne» par 0 et déplacer le compteur de la position actuelle à 1 (sauf si vous êtes à la position 0) l’une de ces fonctions (même le getch sur dos C).

getpass() ne fait pas ce que l’utilisateur demandait à l’origine btw, il veut que les * (qui divulguent toujours la longueur du mot de passe aux personnes derrière lui et regardant son écran, ainsi que dans le tampon de défilement du terminal si il ne le ferme pas après usage). mais sans * est probablement une meilleure idée dans les «environnements non fermés».