在不使用getpass(3)的情况下在C中获取密码?

时间:2009-07-28 20:05:24

标签: c passwords

我可以使用getpass()来获取密码。但是,手册页说:

  

此功能已过时。不使用   它

以符合POSIX标准的方式,从用户终端获取密码而不回显密码的当前方法是什么? [原来我说“便携”,但我的目的是避免使用过时的功能。]

6 个答案:

答案 0 :(得分:14)

这应该适用于linux / macosx,Windows版本应该使用Get/Set ConsoleMode

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

int
main(int argc, char **argv)
{
    struct termios oflags, nflags;
    char password[64];

    /* disabling echo */
    tcgetattr(fileno(stdin), &oflags);
    nflags = oflags;
    nflags.c_lflag &= ~ECHO;
    nflags.c_lflag |= ECHONL;

    if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) {
        perror("tcsetattr");
        return EXIT_FAILURE;
    }

    printf("password: ");
    fgets(password, sizeof(password), stdin);
    password[strlen(password) - 1] = 0;
    printf("you typed '%s'\n", password);

    /* restore terminal */
    if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) {
        perror("tcsetattr");
        return EXIT_FAILURE;
    }

    return 0;
}

答案 1 :(得分:4)

您可以使用ncurses库从标准输入读取,而不会将结果回显到屏幕。 (在获得任何输入之前调用noecho())。该库已存在很长时间,可在各种平台上运行(可以找到Windows版本here

答案 2 :(得分:3)

虽然这是一个已经回答的非常古老的问题,但这是我一直在使用的(这与接受的答案非常相似):

#include <termios.h>
#include <cstdio>

//
// The following is a slightly modifed version taken from:
// http://www.gnu.org/software/libc/manual/html_node/getpass.html
//
ssize_t my_getpass (char *prompt, 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;

    /* Display the prompt */
    if (prompt)
        printf("%s", prompt);

    /* Read the password. */
    nread = getline (lineptr, n, stream);

    /* Remove the carriage return */
    if (nread >= 1 && (*lineptr)[nread - 1] == '\n')
    {
        (*lineptr)[nread-1] = 0;
        nread--;
    }
    printf("\n");

    /* Restore terminal. */
    (void) tcsetattr (fileno (stream), TCSAFLUSH, &_old);

    return nread;
}

//
// Test harness - demonstrate calling my_getpass().
//
int main(int argc, char *argv[])
{
    size_t maxlen = 255;
    char pwd[maxlen];
    char *pPwd = pwd; // <-- haven't figured out how to avoid this.

    int count = my_getpass((char*)"Enter Password: ", &pPwd, &maxlen, stdin);

    printf("Size of password: %d\nPassword in plaintext: %s\n", count, pwd);

    return 0;
}

答案 3 :(得分:2)

根据University of Milwaukee's documentation它已经过时了,因为:

  

getpass()函数不是线程安全的,因为它操作   全球信号状态。

     

计划从未来版本的X / Open CAE规范中撤销getpass()函数。

答案 4 :(得分:1)

在Windows上,您可以使用SetConsoleMode api,描述为here

答案 5 :(得分:0)

另一个适用于Windows的简单解决方案。 包含“ conio.h”

GET /_search
{
  "query": {
    "function_score": {
      "functions": [
        {
          "gauss": {
            "date": {
              "origin": "2013-09-17", 
              "scale": "10d",
              "offset": "5d",
              "decay": 0.5
            }
          }
        }, 
        {
          "weight": 0.25
        }
      ], 
      "score_mode": "max"
    }
  }
}