linux下用c语言如何创建密码

0 views
Skip to first unread message

刘周平

unread,
Sep 14, 2008, 9:43:53 PM9/14/08
to xiyou...@googlegroups.com
这几天我们用c语言编写管理系统,在实现密码管理功能时,不知道怎么去实现,在windows下用getch()可轻松实现,问题是linux下没有getch()这个函数。
有哪位知道在linux下怎么去实现密码管理,请指教,谢谢!

Jianjun Kong

unread,
Sep 14, 2008, 10:42:06 PM9/14/08
to 刘周平, xiyou...@googlegroups.com
On Mon, Sep 15, 2008 at 09:43:53AM +0800, 刘周平 wrote:
>这几天我们用c语言编写管理系统,在实现密码管理功能时,不知道怎么去实现,在
>windows下用getch()可轻松实现,问题是linux下没有getch()这个函数。
>有哪位知道在linux下怎么去实现密码管理,请指教,谢谢!
$ man getpass

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


--
Jianjun Kong | Happy Hacking
HomePage: http://kongove.cn
Gtalk: kongj...@gmail.com

tuzi xiao

unread,
Sep 14, 2008, 11:20:59 PM9/14/08
to Jianjun Kong, 刘周平, xiyou...@googlegroups.com

密码输入关闭回显的两种方法

在软件开发中,往往会遇到要求用户输入密码的情况。出于对密码的保密,输入的字符是不会显示到屏幕上的。例如,在登录Linux系统时,输入用户名后,输入的密码是不显示的。这里介绍两种方法来解决这一问题。

6.5.1  使用curses库

curses库是由柏克莱大学的Bill Joy及Ken Arnold所开发的。当时开发curses库的目的是为了解决程序对于不同终端的兼容性。curses库用于处理Linux/UNIX上的光标移动及屏 幕显示问题。考虑到curses库的复杂性,这里只是简单地介绍一下curses库的使用。需要这方面详细信息可以查阅相关资料。

使用curses库中的函数前,需要进行必要的初始化工作。程序需要使用initscr函数来开启curses模式,在结束前调用endwin函数来关闭curses模式。代码如下:

#include <curses.h>

int main(int argc,char* argv[]){

    initscr();

    endwin();

}

在实际使用中,出于方便的目的,往往把一些初始化的动作放置在初始化函数中,以方便调用。具体代码如下:

void initial()

{

    initscr();

    cbreak();

    nl();

    noecho();

    intrflush(stdscr,FALSE);

    keypad(stdscr,TRUE);

    refresh();

}

代码中使用到了一些curses库的函数,含义如下。

l     cbreak():调用cbreak函数后,除了"Del"和"Ctrl"键外,接受其他所有字符输入。

l     nl()/nonl():输出时,换行是否作为回车字符。nl函数将换行作为回车符,而nonl函数相反。

l     noecho()/echo():关闭/打开输入回显功能。

l     intrflush(WINDOW *win, bool bf):win为标准输出。当bf为true时输入Break,可以加快中断的响应。但是,有可能会造成屏幕输出信息的混乱。

l     keypad(WINDOW *win, bool bf):win为标准输出。调用keypad函数后,将可以使用键盘上的一些特殊字符,如方向键,转化成curses.h中的特殊键。

l     refresh():重绘屏幕显示内容。在调用initscr函数后,第一次调用refresh函数会清除屏幕显示。

程序p6.3.c给出了使用curses库实现密码输入、屏蔽输出结果的实例。具体代码如下:

//p6.3.c 使用curses实现密码输入

#include <stdio.h>

#include <stdlib.h>

#include <curses.h>

#include <unistd.h>

void init()

{

   initscr();

   cbreak();

   nl();

   noecho();

   intrflush(stdscr,FALSE);

   keypad(stdscr,TRUE);

   refresh();

}

int getpasswd(char* passwd, int size)

{

   int c;

   int n = 0;

  

   printw("Please Input password:");

   do{

      c = getch();

      if (c != '\n'){

         echochar('*');//printw("*");

         passwd[n++] = c;

        }

   }while(c != '\n' && n < (size - 1));

   passwd[n] = '\0';

   return n;

}

int main()

{

   char passwd[20];

   int n;

  

   init();

   n=getpasswd(passwd, sizeof(passwd));

  

   printw("\nYour passwd is:%s\n", passwd);

   printw("Press any key continue ...\n");

  

   refresh();

   getchar();

   endwin();

   return 0;

}

使用gcc编译该程序,获得名为p6.5的可执行程序。注意程序中使用了curses库,因此编译时要指明该库的名称。具体编译和执行情况如下:

[program@localhost charter6]$ gcc -o p6.3 p6.3.c -lcurses

[program@localhost charter6]$ ./p6.3

Please Input password:*******

Your passwd is:afdafds

Press any key continue ...

6.5.2  使用tcgetattr函数和tcsetattr函数

还有种方法,可以不使用curses库解决密码输入的回显问题。程序p6.4.c通过使用tcgetattr函数和tcsetattr函数同样达到了目的。具体代码如下:

#include <stdio.h>

#include <termios.h>

#include <unistd.h>

#include <errno.h>

#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL)

//函数set_disp_mode用于控制是否开启输入回显功能

//如果option为0,则关闭回显,为1则打开回显

int set_disp_mode(int fd,int option)

{

   int err;

   struct termios term;

   if(tcgetattr(fd,&term)==-1){

     perror("Cannot get the attribution of the terminal");

     return 1;

   }

   if(option)

       term.c_lflag|=ECHOFLAGS;

   else

       term.c_lflag &=~ECHOFLAGS;

   err=tcsetattr(fd,TCSAFLUSH,&term);

   if(err==-1 && err==EINTR){

       perror("Cannot set the attribution of the terminal");

       return 1;

   }

   return 0;

}

//函数getpasswd用于获得用户输入的密码,并将其存储在指定的字符数组中

int getpasswd(char* passwd, int size)

{

   int c;

   int n = 0;

  

   printf("Please Input password:");

  

   do{

      c=getchar();

      if (c != '\n'|c!='\r'){

         passwd[n++] = c;

      }

   }while(c != '\n' && c !='\r' && n < (size - 1));

   passwd[n] = '\0';

   return n;

}

int main()

{

   char passwd[20];

    

   //首先关闭输出回显,这样输入密码时就不会显示输入的字符信息

   set_disp_mode(STDIN_FILENO,0);

   //调用getpasswd函数获得用户输入的密码

   getpasswd(passwd, sizeof(passwd));

  

   printf("\nYour passwd is:%s\n", passwd);

   printf("Press any key continue ...\n");

 

   set_disp_mode(STDIN_FILENO,1);

   getchar();

   return 0;

}

使用gcc编译p6.4.c代码,获得名为p6.4的可执行程序。执行该程序,得到如下的输出结果:

[program@localhost charter6]$ gcc -o p6.4 p6.4.c

[program@localhost charter6]$ ./p6.4

Please Input password:

Your passwd is:afdfasf

Press any key continue ...

[program@localhost charter6]$

刘周平

unread,
Sep 14, 2008, 11:52:01 PM9/14/08
to tuzi xiao, Jianjun Kong, xiyou...@googlegroups.com


2008/9/15 tuzi xiao <zhan...@gmail.com>

太棒了!你们说的上面几种解决方案都可以实现!谢了!

tuzi xiao

unread,
Sep 14, 2008, 11:57:12 PM9/14/08
to 刘周平, Jianjun Kong, xiyou...@googlegroups.com
不知道linux下有没有和getch功能类似的函数?

Jianjun Kong

unread,
Sep 15, 2008, 12:05:02 AM9/15/08
to 刘周平, Xiyou-Linux-Group
On Mon, Sep 15, 2008 at 11:54:32AM +0800, 刘周平 wrote:
>2008/9/15 Jianjun Kong <kongj...@gmail.com>

> On Mon, Sep 15, 2008 at 09:43:53AM +0800, 刘周平 wrote:
> >这几天我们用c语言编写管理系统,在实现密码管理功能时,不知道怎么去实现,在
> >windows下用getch()可轻松实现,问题是linux下没有getch()这个函数。
> >有哪位知道在linux下怎么去实现密码管理,请指教,谢谢!
> $ man getpass
>
> #include <unistd.h>
> char *getpass( const char * prompt );
>
> 这方法非常好用啊,比windows下的getch()更方便,谢了!

Linux上提示密码输入都不回显"*"之类的符号,暴露密码的位数也会给破解带来方便 ;-)

tuzi xiao

unread,
Sep 15, 2008, 12:07:56 AM9/15/08
to Jianjun Kong, 刘周平, Xiyou-Linux-Group


2008/9/15 Jianjun Kong <kongj...@gmail.com>
On Mon, Sep 15, 2008 at 11:54:32AM +0800, 刘周平 wrote:
>2008/9/15 Jianjun Kong <kongj...@gmail.com>
>    On Mon, Sep 15, 2008 at 09:43:53AM +0800, 刘周平 wrote:
>    >这几天我们用c语言编写管理系统,在实现密码管理功能时,不知道怎么去实现,在
>    >windows下用getch()可轻松实现,问题是linux下没有getch()这个函数。
>    >有哪位知道在linux下怎么去实现密码管理,请指教,谢谢!
>    $ man getpass
>
>    #include <unistd.h>
>    char *getpass( const char * prompt );
>
>    这方法非常好用啊,比windows下的getch()更方便,谢了!

Linux上提示密码输入都不回显"*"之类的符号,暴露密码的位数也会给破解带来方便 ;-)

呵呵!可是人家老师要求回显星号,getpass好像不能实现吧。


潘猛

unread,
Sep 15, 2008, 12:26:40 AM9/15/08
to tuzi xiao, Jianjun Kong, 刘周平, Xiyou-Linux-Group
首先getch函数调用时是不回显的,我想要回显的话,可以根据密码的长度在自己输出相应长度的 ' * ' 就可以了

2008/9/15 tuzi xiao <zhan...@gmail.com>:

贾孟树

unread,
Sep 15, 2008, 12:39:59 AM9/15/08
to Jianjun Kong, 刘周平, xiyou...@googlegroups.com
getpass这个函数好像已经不推荐使用了
char Getch(void) /*The implemention of the getch() fuction in *nix
systerm*/
{
char ch;
struct termios oldt, newt;

tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ECHO|ICANON);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);

return ch;
}
用这个吧。

在 2008-09-15一的 10:42 +0800,Jianjun Kong写道:

Jianjun Kong

unread,
Sep 15, 2008, 2:43:42 AM9/15/08
to 贾孟树, 刘周平, xiyou...@googlegroups.com
On Mon, Sep 15, 2008 at 12:39:59PM +0800, 贾孟树 wrote:
>getpass这个函数好像已经不推荐使用了
>char Getch(void) /*The implemention of the getch() fuction in *nix
>systerm*/
>{
> char ch;
> struct termios oldt, newt;
>
> tcgetattr(STDIN_FILENO, &oldt);
> newt = oldt;
> newt.c_lflag &= ~(ECHO|ICANON);
> tcsetattr(STDIN_FILENO, TCSANOW, &newt);
> ch = getchar();
> tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
>
> return ch;
>}
>用这个吧。

这个条件都满足了。
需要头文件:
#include <stdio.h>
#include <unistd.h>
#include <termios.h>

BTW:贾老大潜水已久呀~~

Reply all
Reply to author
Forward
0 new messages