터미널에서 암호 입력 숨기기
암호를 쓰는 동안 암호를 숨기고 싶은 경우*
나는 이 코드에 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;
}
것이다.GCC
포함하지 않음conio.h
그래서,getch()
누구 있어해결책은 있는 사람?
Linux 세계에서는 일반적으로 마스킹이 별표를 사용하여 수행되지 않으며, 일반적으로 에코가 꺼지고 사용 시 터미널에 공백이 표시됨(예:su
또는 가상 터미널 등에 로그인하십시오.
비밀번호 입력을 처리하는 라이브러리 기능이 있는데, 별표로 비밀번호를 가리는 것이 아니라, 단말기에 대한 암호 반향이 불가능해진다.내가 가지고 있는 리눅스 북에서 이걸 꺼냈다.양전자 표준의 일부분인 것 같아
#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)의 모든 처리를 비활성화한다.
그런 다음 프롬프트로 가리킨 문자열을 인쇄하고 입력 라인을 읽으며, 기능 결과로 후행 뉴라인이 벗겨진 상태에서 null-terminated 입력 문자열을 반환한다.
getpass()를 검색하는 구글 검색은 GNU 구현에 대한 참조 자료(대부분의 Linux 디스트로에 있어야 함)와 필요할 경우 자신의 구현을 위한 일부 샘플 코드를 가지고 있다.
http://www.gnu.org/s/hello/manual/libc/getpass.html
나만의 롤링 예:
#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;
}
필요한 경우 이를 기반으로 별표를 표시하도록 수정하십시오.
것은getch
낡은 것에 의존하고 피하다getpass
, 권장 접근방식은 다음을 통해 단자 ECO를 비활성화하는 것이다.termios
사용. 유연한 암호 통조림 루틴을 찾기 위해 몇 번 검색한 결과, C와 독립적으로 사용할 수 있는 암호는 극히 적다는 사실에 놀랐다.단순히 재코딩하는 것이 아니라getch
임기응변으로c_lflag
선택사항, 약간 더 일반화된 접근방식은 단지 몇 가지 추가사항을 필요로 한다.교체 그 이상getch
모든 루틴은 오버플로를 방지하기 위해 지정된 최대 길이를 적용해야 하며, 사용자가 최대값을 초과하여 들어가려고 할 경우 잘라내야 하며, 잘라내기 발생 시 경고해야 한다.
아래, 추가된 내용들은 어떤 것들로부터도 읽기를 허용한다.FILE *
입력 스트림은 길이를 지정된 길이로 제한하며, 입력 시 편집(백스페이스) 기능을 최소화하고, 문자 마스크를 지정하거나 완전히 비활성화할 수 있으며, 마지막으로 입력한 암호의 길이를 반환한다.입력한 암호가 최대 길이 또는 지정된 길이로 잘렸을 때 경고가 추가되었다.
유사한 해결책을 찾는 이 질문을 통해 다른 사람들에게 유용하게 쓰일 수 있기를 바란다.
#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 */
}
그 용도를 보여주는 간단한 프로그램은 다음과 같다.암호를 고정하는 데 정적 문자 배열을 사용하는 경우 포인터가 함수에 전달되는지 확인하십시오.
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;
}
출력 예제
$ ./bin/getpasswd2
Enter password: ******
you entered : 123456 (6 chars)
Enter password:
you entered : abcdef (6 chars)
의 기지의 getch
는이 수
#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;
}
당신의 접근 방식이 완벽하지 않다는 점에 유의하십시오. 이러한 것들을 처리하기 위해 ncurs나 다른 터미널 라이브러리와 같은 것을 사용하는 것이 더 낫다.
나만의 것을 만들 수 있음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;
}
데모 코드:
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;
}
방법은 올바르지만 암호를 입력하는 동안 터미널 에코를 끄십시오.
#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);
}
대신에getch()
, 왜 그냥 사용하지 않는가?getc()
대신에?
내 문제를 해결할 수 있는 도움과 지원을 주신 여러분 모두에게 감사해.나는 리눅스 안에서 나에게 가장 잘 맞는 비밀번호를 숨길 수 있는 최선의 방법을 찾는다.getpass() 함수를 사용한다.그것은 단지 "unistd"를 포함시킬 필요가 있다.h" 파일.
getpass 함수의 동기화:
char * getpass (const char *pass)
매개 변수: 프롬프트: 암호를 요청하는 동안 인쇄할 문자열 포인터
반환 값: 암호 문자열 포인터
예:
#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;
}
출력:
암호 입력:
heet
Windows에서 휴대할 필요가 없다면 ncurs.h를 사용할 수도 있지만, 여기 좀 더 "이동식" 버전이 있다.
휴대할 필요가 없는 경우 ncurs 솔루션을 선택하십시오.
휴대용게치.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
그리고 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;
}
그것은 너의 문제와 잘 맞을 것이다.
그게 도움이 되길 바래.
#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;
}
그냥 이 조각들을 복사해서 사용해.도움이 되었기를 바란다.
불행히도 C 표준 도서관에는 박스 밖으로 그런 기능이 없다.제3자 도서관에서나.
한 가지 옵션은 ANSI 이스케이프 시퀀스를 사용하여 배경색을 콘솔의 전경색으로 설정하여 암호를 숨기는 것이다.이 링크를 사용해 보십시오.
문자를 스캔하면 버퍼에 넣을 수 있다.또한 백스페이스를 누른 경우 코드를 작성하고 삽입된 암호를 적절하게 수정해야 한다.
여기 내가 한때 저주를 가지고 썼던 암호가 있다.컴파일 대상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] = '\0';
endwin ();
return pass;
}
C에서 당신은 사용할 수 있다.getpasswd()
을 하는 것이 기기다.stty
셸에서, 예:
#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;
}
다음은 사용하는 동등한 셸 스크립트stty
(이 설정은 사용자의 설정을 변경함)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
출처: C에 반향하지 않고 어떻게 암호를 읽을 수 있는가?
남자 getpass
이 기능은 구식이다.사용하지 마십시오.단자 에코가 활성화되지 않은 상태에서 입력을 읽으려면 termios(3)의 ECO 플래그 설명을 참조하십시오.
# include <termios.h>
# include <unistd.h> /* needed for STDIN_FILENO which is an int file descriptor */
struct termios tp, save;
tcgetattr( STDIN_FILENO, &tp); /* get existing terminal properties */
save = tp; /* save existing terminal properties */
tp.c_lflag &= ~ECHO; /* only cause terminal echo off */
tcsetattr( STDIN_FILENO, TCSAFLUSH, &tp ); /* set terminal settings */
/*
now input by user in terminal will not be displayed
and cursor will not move
*/
tcsetattr( STDIN_FILENO, TCSANOW, &save); /* restore original terminal settings */
현재 대부분의 Linux distro는 암호를 별표로 숨기지 않는다.그렇게 하면 비밀번호의 길이가 누설되어 결코 이롭지 않다.암호를 입력했을 때 커서가 움직이지 않도록 하는 것이 쉽고 좋다.만약 어떤 이유로든 당신이 필요로 한다면*
입력된 모든 문자를 인쇄하려면 먼저 모든 키를 누를 수 있어야 한다.Enter
항상 문제가 있었어
printf("\nENTER PASSWORD: ");
while (1)
{
ch=getch();
if(ch==13) //ON ENTER PRESS
break;
else if(ch==8) //ON BACKSPACE PRESS REMOVES CHARACTER
{
if(i>0)
{
i--;
password[i]='\0';
printf("\b \b");
}
}
else if (ch==32 || ch==9) //ON PRESSING TAB OR SPACE KEY
continue;
else
{
password[i]=ch;
i++;
printf("*");
}
}
password[i]='\0';
여기 C++ 공식 사이트로부터 각색된 내 아이디어가 있다.
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
string getpass(const char *prompt, bool showchar = false, char echochar = '*')
{
struct termios oi, ni;
tcgetattr(STDIN_FILENO, &oi);
ni = oi;
ni.c_lflag &= ~(ICANON | ECHO);
const char DELETE = 127;
const char RETURN = 10;
string password;
unsigned char ch = 0;
cout << prompt;
tcsetattr(STDIN_FILENO, TCSANOW, &ni);
while (getchar() != RETURN) {
if (ch == DELETE) {
if(password.length != 0){
if (showchar) cout << "\b \b";
password.resize(password.length() - 1);
}
}else {
password += getchar();
if (showchar) cout << echochar;
}
}
tcsetattr(STDIN_FILENO,TCSANOW,&oi)
cout << endl;
return password;
}
한 문자를 한 번에 읽고 문자열로 추가하며 다른 문자를 보여주는 것을 지원한다.
ICANON termios lflag는 처리 캐리지 리턴/라인피드를 끄고, 음의 ECO termios 설정은 STDIN에 대해 에코를 해제한다는 점에 유의한다.
암호 읽기 및 인쇄에 에코 사용 여부와 상관 없이 이 기능을 사용할 경우'*'
입력된 문자의 경우, 단순히 새 줄/새 줄 리턴을 만날 때까지 문자를 읽는 문제가 아니라, '스트링 빌드 루틴'에서 백스페이스를 처리해야 한다(백스페이스가 실제 문자열로 끝나는 경우, 다양한 문자열 기반 입력 f와 같은 경우처럼 문자가 제거되지 않도록 함).분리하다
것이다. DOS의 CTO DOS의 CTO DOW DOW DOW DOWD의 Getch To도 그것은 또한 행복하게 돌아올 것이다.0x08
백스페이스용(또는 127개 또는 특정 OS에서 백스페이스로 사용하는 것)
'삭제 안 함 - 문자열 시작 전'을 추적하고, ' 문자열의 새 끝'을 0으로 교체하고, 현재 위치 카운터를 1개 뒤로 이동(위치 0에 있지 않는 한), 이러한 기능 중 하나를 가진 프로그래머에게 달려 있다(도스 C에 있는 게치까지).
getpass()
사용자가 원래 btw를 요청한 것을 하지 않고, 그는 *의 (사용 후 닫지 않으면 단말기의 스크롤버퍼뿐만 아니라 뒤에 서서 자신의 화면을 보는 사람들에게도 비밀번호의 길이를 공개한다.)를 원한다.그러나 *'s가 없는 것이 '비 폐쇄 환경'에서는 더 좋은 생각일 것이다.
참조URL: https://stackoverflow.com/questions/6856635/hide-password-input-on-terminal
'programing' 카테고리의 다른 글
NoClassDefoundError - Eclipse 및 Android (0) | 2022.04.17 |
---|---|
Vuex 스토어가 자동으로 업데이트됨 (0) | 2022.04.17 |
v-select를 복제 및 필터링 (0) | 2022.04.17 |
깊은 중첩 객체의 반응성이 작동하지 않음 (0) | 2022.04.17 |
Vuex 반환 "TypeError: 정의되지 않은 속성 '게터'를 읽을 수 없음" (0) | 2022.04.17 |