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

Jer*_*ner 22 c passwords

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

此功能已过时.不要使用它.

从POSIX兼容的方式,从用户终端获取密码而不回显密码的当前方法是什么?[原来我说"便携",但我的目的是避免使用过时的功能.]

dfa*_*dfa 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;
}
Run Code Online (Sandbox Code Playgroud)

  • 您应该在尝试stdin之前首先使用/ dev/tty,就好像您正在使用管道一样,stdin将是管道内容,而不是终端输入. (4认同)
  • `password [strlen(password) - 1] = 0;` - 这是非常错误的. (4认同)
  • 我不介意看到char密码[64] = {0}; 或者如果它是可重入的,则使用它之前的memset (3认同)
  • `password[strlen(password) - 1] = 0;` 仅删除存在的换行符,否则它会错误地删除密码的最后一个字符。`password[ strcspn(password, "\n" ) ] = '\0'` [始终有效](https://port70.net/~nsz/c/c11/n1570.html#7.24.5.3)。 (2认同)

小智 5

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


Van*_*gan 5

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

\n\n
#include <termios.h>\n#include <cstdio>\n\n//\n// The following is a slightly modifed version taken from:\n// http://www.gnu.org/software/libc/manual/html_node/getpass.html\n//\nssize_t my_getpass (char *prompt, char **lineptr, size_t *n, FILE *stream)\n{\n    struct termios _old, _new;\n    int nread;\n\n    /* Turn echoing off and fail if we can\xe2\x80\x99t. */\n    if (tcgetattr (fileno (stream), &_old) != 0)\n        return -1;\n    _new = _old;\n    _new.c_lflag &= ~ECHO;\n    if (tcsetattr (fileno (stream), TCSAFLUSH, &_new) != 0)\n        return -1;\n\n    /* Display the prompt */\n    if (prompt)\n        printf("%s", prompt);\n\n    /* Read the password. */\n    nread = getline (lineptr, n, stream);\n\n    /* Remove the carriage return */\n    if (nread >= 1 && (*lineptr)[nread - 1] == \'\\n\')\n    {\n        (*lineptr)[nread-1] = 0;\n        nread--;\n    }\n    printf("\\n");\n\n    /* Restore terminal. */\n    (void) tcsetattr (fileno (stream), TCSAFLUSH, &_old);\n\n    return nread;\n}\n\n//\n// Test harness - demonstrate calling my_getpass().\n//\nint main(int argc, char *argv[])\n{\n    size_t maxlen = 255;\n    char pwd[maxlen];\n    char *pPwd = pwd; // <-- haven\'t figured out how to avoid this.\n\n    int count = my_getpass((char*)"Enter Password: ", &pPwd, &maxlen, stdin);\n\n    printf("Size of password: %d\\nPassword in plaintext: %s\\n", count, pwd);\n\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n