开元食味
德国频道
查看: 1542|回复: 0
打印 上一主题 下一主题

[转贴]Linux程式设计入门 - crypt

[复制链接]
1#
发表于 7.2.2003 07:55:44 | 只看该作者
即时机票
BBS水木清华站∶精华区 <br>发信人: reden (Offer 快快来啊 ~&#33;), 信区: Linux <br>标  题: Linux程式设计入门 - crypt <br>发信站: BBS 水木清华站 (Thu Apr  1 19:56:43 1999) <br>  <br>Linux程式设计入门 - crypt <br>  <br>  <br>  <br>  crypt是个密码加密函数,它是基於Data Encryption Standard(DES)演算法。 <br>  <br>  crypt基本上是One way encryption,因此它只适用於密码的使用,不适合於资 <br>  <br>  料加密。 <br>  <br>  <br>  char *crypt(const char *key, const char *salt); <br>  <br>  <br>  key是使用者的密码。salt是两个字,每个字可从[a-zA-Z0-9./]中选出来,因 <br>  <br>  此同一密码增加了4096种可能性。透过使用key中每个字的低七位元,取得 <br>  <br>  56-bit关键字,这56-bit关键字被用来加密成一组字,这组字有13个可显示的 <br>  <br>  ASCII字,包含开头两个salt。 <br>  <br>  <br>  crypt在您有自行管理使用者的场合时使用,例如会员网站、BBS等等。 <br>  <br>  <br>  <br>  范例一 :  crypt_word.c <br>  <br>  <br>  #include &lt;stdio.h&gt; <br>  <br>  #include &lt;stdlib.h&gt; <br>  <br>  #include &lt;unistd.h&gt; <br>  <br>  <br>  void main(int argc,char **argv) <br>  <br>  { <br>  <br>    if (argc&#33;=3) exit(0); <br>  <br>    printf(&quot;%s\n&quot;,crypt(argv[1],argv[2])); <br>  <br>  } <br>  <br>  <br>  编译 <br>  <br>  <br>  gcc -o crypt_word crypt.c -lcrypt <br>  <br>  <br>  检验 <br>  <br>  <br>  请先看您的/etc/passwd,找一个您自己的帐号,看前面两个字,那是您自己的 <br>  <br>  salt。接下来输入: <br>  <br>  <br>  ./crypt_word your_password salt <br>  <br>  <br>  看看它们是否相同(应该要相同,除非您加了crypt plugin或使用不同的crypt <br>  <br>  function,例如shadow、pam,这种状况下,加密字是不同的),另外检验看看 <br>  <br>  他们是否为13个字。 <br>  <br>  <br>  您也可以利用Apache上所附的htpasswd来产生加密字做为验证。 <br>  <br>  <br>  范例二: verify_passwd.c <br>  <br>  <br>  注意,这个范例读取/etc/passwd的资料,不适用於使用shadow或已经使用pam <br>  <br>  的系统(例如slackware,RedHat及Debian在不外加crypt plugin的状况下,应 <br>  <br>  当相同)。此范例仅供叁考,做为了解crypt函数运作的情形,真正撰写程式 <br>  <br>  时,应该避免类似的写法。 <br>  <br>  <br>  #include &lt;stdio.h&gt; <br>  <br>  #include &lt;stdlib.h&gt; <br>  <br>  #include &lt;unistd.h&gt; <br>  <br>  <br>  typedef struct { <br>  <br>    char username[64]; <br>  <br>    char passwd[16]; <br>  <br>    int  uid; <br>  <br>    int  gid; <br>  <br>    char name[256]; <br>  <br>    char root[256]; <br>  <br>    char shell[256]; <br>  <br>  } account; <br>  <br>  <br>  /* 注意&#33; 以下的写法,真实世界的软体开发状况下,千万不要用&#33; */ <br>  <br>  int acc_info(char *info,account *user) <br>  <br>  { <br>  <br>    char * start = info; <br>  <br>    char * now = info; <br>  <br>  <br>    /* username */ <br>  <br>    while (*now&&*now&#33;=&#39;:&#39;) now++; /* 这是超级大安全漏洞 */ <br>  <br>    if (&#33;*now) return 0; <br>  <br>    *now = 0; now++; <br>  <br>    strcpy(user-&gt;username,start); /* 这会导致buffer overflow */ <br>  <br>    start = now; <br>  <br>    /* passwd */ <br>  <br>    while (*now&&*now&#33;=&#39;:&#39;) now++; /* 这是超级大安全漏洞 */ <br>  <br>    if (&#33;*now) return 0; <br>  <br>    *now = 0; now++; <br>  <br>    strcpy(user-&gt;passwd,start); /* 这会导致buffer overflow */ <br>  <br>    start = now; <br>  <br>    /* uid */ <br>  <br>    while (*now&&*now&#33;=&#39;:&#39;) now++; <br>  <br>    if (&#33;*now) return 0; <br>  <br>    *now = 0; now++; <br>  <br>    user-&gt;uid = atoi(start); <br>  <br>    start = now; <br>  <br>    /* gid */ <br>  <br>    while (*now&&*now&#33;=&#39;:&#39;) now++; <br>  <br>    if (&#33;*now) return 0; <br>  <br>    *now = 0; now++; <br>  <br>    user-&gt;gid = atoi(start); <br>  <br>    start = now; <br>  <br>    /* name */ <br>  <br>    while (*now&&*now&#33;=&#39;:&#39;) now++; /* 这是超级大安全漏洞 */ <br>  <br>    if (&#33;*now) return 0; <br>  <br>    *now = 0; now++; <br>  <br>    strcpy(user-&gt;name,start); /* 这会导致buffer overflow */ <br>  <br>    start = now; <br>  <br>    /* root */ <br>  <br>    while (*now&&*now&#33;=&#39;:&#39;) now++; /* 这是超级大安全漏洞 */ <br>  <br>    if (&#33;*now) return 0; <br>  <br>    *now = 0; now++; <br>  <br>    strcpy(user-&gt;root,start); /* 这会导致buffer overflow */ <br>  <br>    start = now; <br>  <br>    /* shell */ <br>  <br>    while (*now&&*now&#33;=&#39;:&#39;) now++; /* 这是超级大安全漏洞 */ <br>  <br>    *now = 0; now++; <br>  <br>    strcpy(user-&gt;shell,start); /* 这会导致buffer overflow */ <br>  <br>    start = now; <br>  <br>    return 1; <br>  <br>  } <br>  <br>  <br>  int read_password(char *filename,account *users) <br>  <br>  { <br>  <br>    FILE *fp; <br>  <br>    char buf[1024]; <br>  <br>    int n; <br>  <br>  <br>    n = 0; <br>  <br>    fp = fopen(filename,&quot;rt&quot;); <br>  <br>    while (fgets(buf,1024,fp)&#33;=NULL) { <br>  <br>      if (acc_info(buf,&users[n])) n++; <br>  <br>    } <br>  <br>    fclose(fp); <br>  <br>    return n; <br>  <br>  } <br>  <br>  <br>  void main(int argc,char **argv) <br>  <br>  { <br>  <br>    int n,i,done; <br>  <br>    account ACC[128]; <br>  <br>    char username[256]; <br>  <br>    char password[256]; <br>  <br>    char * passwd; <br>  <br>    char salt[4]; <br>  <br>  <br>    if (argc&lt;2) { <br>  <br>      printf(&quot;username:&quot;); <br>  <br>      scanf(&quot;%s&quot;,username); /* 这是超级大安全漏洞 */ <br>  <br>    } else strcpy(username,argv[1]); /* 这是超级大安全漏洞 */ <br>  <br>    if (argc&lt;3) { <br>  <br>      printf(&quot;password:&quot;); <br>  <br>      scanf(&quot;%s&quot;,password); /* 这是超级大安全漏洞 */ <br>  <br>    } else strcpy(password,argv[2]); /* 这是超级大安全漏洞 */ <br>  <br>  <br>    n = read_password(&quot;/etc/passwd&quot;,ACC); <br>  <br>  <br>    for (i=0,done=0;i&lt;n;i++) <br>  <br>      if (strcmp(username,ACC.username)==0) { <br>  <br>        salt[0] = ACC.passwd[0]; <br>  <br>        salt[1] = ACC.passwd[1]; <br>  <br>        salt[2] = 0; <br>  <br>        passwd = crypt(password,salt); <br>  <br>        printf(&quot;%s %s %s\n&quot;,ACC.username,ACC.passwd,passwd); <br>  <br>        if (strcmp(passwd,ACC.passwd)==0) { <br>  <br>          printf(&quot;login successfully&#33;\n&quot;); <br>  <br>        } else { <br>  <br>          printf(&quot;incorrect password&#33;\n&quot;); <br>  <br>        } <br>  <br>        done = 1; <br>  <br>      } <br>  <br>    if (&#33;done) printf(&quot;invalid username&#33;\n&quot;); <br>  <br>  } <br>  <br>  <br>  编译 <br>  <br>  <br>  gcc -o verify_passwd verify_passwd.c -lcrypt <br>  <br>  <br>  检验 <br>  <br>  <br>  ./verify_passwd your_username your_password <br>  <br>  <br>  避免安全漏洞 <br>  <br>  <br>  buffer overflow是个很严重的安全漏洞,通常您不可使用像char buf[xxxx]的 <br>  <br>  宣告。在这一类与安全有相关的任何程式写作中(不是只有密码,例如像 <br>  <br>  www/ftp/telnet的这一类对外窗口都要算在内),您应该要先检查字串长度。例 <br>  <br>  如以下例子: <br>  <br>  <br>  len = strlen(incoming_username); <br>  <br>  if (len&gt;xxx) invalid; <br>  <br>  new_string = (char*)malloc(len+1); <br>  <br>  strcpy(new_string,incoming_username); <br>  <br>  your_own_operations... <br>  <br>  <br>  如此才能避免buffer overflow,万万不可滥做假设,切记切记,连许多数十年 <br>  <br>  经验丰富的老手都会犯这个错误。 <br>  <br>  <br>  <br>  与crypt函数相关者尚有以下三个: <br>  <br>  <br>  void setkey (const char *key); <br>  <br>  void encrypt (char *block, int edflag); <br>  <br>  void swab (const char *from, char *to, ssize_t n); <br>  <br>  <br>  一般来说,除非您有特殊需求,你不会用到这三个。 <br>  <br>  <br>  <br>  OK STATION, Webmaster, Brian Lin <br><br>  <br>  <br>  <br>  <br>-- <br>在江湖中,只要拿起了刀,就是一场无涯的梦。 <br>  <br>※ 来源:·BBS 水木清华站 bbs.net.tsinghua.edu.cn·[FROM: 159.226.21.168] <br>  <br>BBS水木清华站∶精华区 <br>  <br>【 在 lul (love my pearl) 的大作中提到: 】 <br>: 这里有MD5的算法 <br>: <a href='ftp://ftp.cs.wisc.edu/ghost/packages/md5.tar.gz' target='_blank'>ftp://ftp.cs.wisc.edu/ghost/packages/md5.tar.gz</a> <br>: 【 在 dietkoke (12 FL OZ) 的大作中提到: 】 <br>: : I see. Thanks&#33; <br>: : Any programming interface for MD5? I don&#39;t see any man pages <br>: : about it?  
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

站点信息

站点统计| 举报| Archiver| 手机版| 小黑屋

Powered by Discuz! X3.2 © 2001-2014 Comsenz Inc.

GMT+1, 23.5.2024 17:28

关于我们|Apps

() 开元网

快速回复 返回顶部 返回列表