Linux 隐藏终端上的密码输入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6856635/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 05:19:11  来源:igfitidea点击:

Hide password input on terminal

clinux

提问by Hit's

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

我想在用*. 我将 Linux GCC 用于此代码。我知道一种解决方案是使用这样的getch()功能

#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 GCCdoes not include conio.hfile so, getch()is useless for me. Does anyone have a solution?

但问题是GCC不包含conio.h文件,所以getch()对我来说没用。有没有人有办法解决吗?

采纳答案by matt

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 suor log into a virtual terminal etc.

在 Linux 世界中,屏蔽通常不使用星号完成,通常只是关闭回显并且终端显示空白例如,如果您使用su或登录虚拟终端等。

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

有一个库函数来处理获取密码,它不会用星号掩盖密码,但会禁止将密码回显到终端。我从我拥有的一本 linux 书中提取了这个。我相信它是 posix 标准的一部分

#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.

#include <unistd.h>
char *getpass(const char *prompt);

/*Returns pointer to statically allocated input password string
on success, or NULL on error*/

getpass() 函数首先禁用回显和所有终端特殊字符(例如中断字符,通常是 Control-C)的处理。

然后它打印提示指向的字符串,并读取一行输入,返回以空字符结尾的输入字符串,去掉尾部的换行符,作为它的函数结果。

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

谷歌搜索 getpass() 引用了 GNU 实现(应该在大多数 linux 发行版中)和一些示例代码,用于在需要时实现您自己的

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

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.

如果需要,您可以将其用作修改它以显示星号的基础。

回答by Susam Pal

You can create your own getch()function on Linux in this manner.

您可以通过getch()这种方式在 Linux 上创建自己的函数。

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

Demo code:

演示代码:

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

回答by Delan Azabani

The functionality of getch(which is a non-standard, Windows function) can be emulated with this code:

的功能getch(这是一个非标准的 Windows 函数)可以用以下代码模拟:

#include <termios.h>
#include <unistd.h>
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;
}

Note that your approach is not perfect - it's better to use something like ncursesor another terminal library to handle these things.

请注意,您的方法并不完美 - 最好使用类似ncurses或其他终端库来处理这些事情。

回答by Constantinius

Unfortunately in the C standard library there is no such function out of the box. Maybe in third party library.

不幸的是,在 C 标准库中没有这样的功能。也许在第三方库中。

One option is use ANSI escape sequences to set the background color to foreground color in the console to conceal the password. Try this link.

一种选择是使用 ANSI 转义序列在控制台中将背景颜色设置为前景色以隐藏密码。试试这个链接

回答by trojanfoe

Your method is correct, however you'll need to turn off terminal echo while the password is being entered:

您的方法是正确的,但是您需要在输入密码时关闭终端回显:

#include <sgtty.h>

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

Instead of getch(), why not just use getc()instead?

而不是getch(),为什么不直接使用getc()呢?

回答by Daniel Leschkowski

You might use ncurses.h if it is not necessary to be portable onto Windows for that, but here is some kind of a more "portable" version:

如果不需要为此可移植到 Windows 上,您可以使用 ncurses.h,但这里有一些更“可移植”的版本:

If it is not necessery to be portable ill point you to a ncurses solution

如果不需要便携,请指向 ncurses 解决方案

portablegetch.h

便携版

/*portablegetch.h*/
#ifndef PGETCH
#define PGETCH
#ifdef __unix__
#include <termios.h>
#include <unistd.h>

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 <conio.h>
#endif
#endif

And the c-file

和c文件

whatever.c

随便.c

#include <stdio.h>
#include <stdlib.h>
#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;
}

That should fit to your problem.

那应该适合你的问题。

Hope that helps.

希望有帮助。

回答by phoxis

With scanning the characters you can take it into a buffer. Also you need to write code if backspace is pressed, and appropriately correct the inserted password.

通过扫描字符,您可以将其放入缓冲区。如果按下退格键,您还需要编写代码,并适当更正插入的密码。

Here is a code which once i wrote with the curses. Compile with gcc file.c -o pass_prog -lcurses

这是我曾经用诅咒编写的代码。编译gcc file.c -o pass_prog -lcurses

#include <stdio.h>
#include <stdlib.h>
#include <curses.h>

#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 string with NUL */
  pass[i] = '
#include <stdio.h>
#include <unistd.h>   
int main()
{
    char *password; // password string pointer
    password = getpass("Enter Password: "); // get a password
    printf("%s\n",password); // this is just for conformation
                             // that password stored successfully
    return 1;
}
'; endwin (); return pass; }

回答by Hit's

Thanks all of you whose help & support to solve my problem. I find a best way to hide my password in linux that fits me best. To use getpass() function. It just need to include "unistd.h" file.

感谢大家的帮助和支持来解决我的问题。我找到了最适合我的在 linux 中隐藏密码的最佳方法。使用 getpass() 函数。它只需要包含“unistd.h”文件。

syntex of getpass function:

getpass 函数的语法:

char * getpass (const char *prompt)

char * getpass (const char *prompt)

Parameters: prompt: string pointer to print while asking for Password

参数:prompt:要求输入密码时打印的字符串指针

Return Value: string pointer of password

返回值:密码字符串指针

Example:

例子:

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

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

output:

输出:

Enter Password:

输入密码:

heet

回答by niko

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

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

Just copy these snippet and use it. Hope it helped

只需复制这些片段并使用它。希望有帮助

回答by kenorb

In C you can use getpasswd()function which pretty much doing similar thing as sttyin shell, example:

在 C 中,您可以使用在 shell 中getpasswd()执行类似操作的函数stty,例如:

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

Here is equivalent shell script which use stty(which changes the settings of your tty):

这是使用的等效 shell 脚本stty(它会更改您的设置tty):

##代码##

Source: How can I read a password without echoing it in C?

来源:如何在不使用 C 语言回显的情况下读取密码?