zoukankan      html  css  js  c++  java
  • 一个玩具程序——测试密码强度(pure C)

    替人写的C语言作业…

    介绍:

    程序名称:
    密码强度检测程序

    注释风格:
    doxygen

    测试环境:
    linux3.6, gcc4.7
    window7, vs2012

    已知问题:
    1. 算法与参考链接不一致,结果会有差别,详见代码注释。
    2. 在vs下可能会编译不通过,将后缀改为cpp就可以了。vs的C编译器实现对C90支持不佳,gcc4.5以上可以正常编译通过。

     1 #ifndef CHECKPASS_H_INCLUDED
     2 #define CHECKPASS_H_INCLUDED
     3 
     4 /*!
     5  * rief   本程序用于检测密码强度
     6  * details 请根据提示输入密码,程序会自动输出对应的强度
     7  *
     8  *          程序会根据是否满足一定的条件对密码进行打分,然后区分出档次。
     9  *          得分最低0分,最高100分;等级分为很弱-弱-一般-好-强-极强几个档次。
    10  *          判断标准(参考[链接](http://goo.gl/wuQdN):
    11  *          1. 最低要求包括
    12  *             * 长度>8位
    13  *             * 以下四种元素至少有三种:
    14  *               - 大写英文字母
    15  *               - 小写英文字母
    16  *               - 数字
    17  *               - 特殊符号
    18  *          2. 加分条件
    19  *             * 密码总字数  +(次数*4)
    20  *             * 大写字母数  +(长度-字数)*2 [字数必须>0]
    21  *             * 小写字母数  +(长度-字数)*2 [同上]
    22  *             * 数字个数    +(次数*4)
    23  *             * 特殊符号数  +(次数*6)
    24  *             * 数字或符号出现在密码中间部分 +(次数*2)
    25  *             * 达到最低需求 +(次数*2)
    26  *          3. 减分条件
    27  *             * 只有字母   -次数
    28  *             * 只有数字   -次数
    29  *             * 出现重复单元,对每个重复的字符  -次数*(次数-1) [不计大小写]
    30  *             * 连续大写字母 -次数*2
    31  *             * 连续小写字母 -次数*2
    32  *             * 连续多个数字 -次数*2
    33  *             * 字母顺序递增/减(三个及以上) -次数*3
    34  *             * 数字顺序递增/减(三个及以上) -次数*3
    35  *
    36  * author
    37  * date 2013-06-22
    38  * copyright GNU Public License
    39  */
    40 
    41 /** 字符数目,取char的最大值+1*/
    42 #define CHARNUM 256
    43 
    44 /** 强度评价*/
    45 extern const char *g_pPasswordLevel[];
    46 
    47 /** 强度枚举*/
    48 typedef enum _PasswordLevel {
    49     VERYWEEK,
    50     WEEK,
    51     AVERAGE,
    52     GOOD,
    53     STRONG,
    54     VERYSTRONG
    55 } PasswordLevel;
    56 
    57 
    58 /** 计算得分需要的参数*/
    59 typedef struct _RuleParameter {
    60     int nLength;      ///< 密码长度
    61     int nUpper;       ///< 大写字母个数
    62     int nLower;       ///< 小写字母个数
    63     int nDigit;       ///< 数字个数
    64     int nSymbol;      ///< 特殊字符个数
    65     int nMidDigitSymbol; ///< 中间部分的数字或字符个数
    66     int nRequirement; ///< 达到最低需求的次数
    67     int RepeatChar[CHARNUM];  ///< 每个字符重复的次数
    68     int nConsecUpper; ///< 连续大写字母个数
    69     int nConsecLower; ///< 连续小写字母个数
    70     int nConsecDigit; ///< 连续数字个数
    71     int nSequence;     ///< (三个及以上)顺序字母/数字次数
    72 } RuleParameter;
    73 
    74 /**
    75  * rief 求密码得分
    76  * param[in] password 密码
    77  * 
    eturn 得分
    78  */
    79 int GetPasswordScore(const char *password);
    80 
    81 /**
    82  * rief 求密码等级
    83  * param[in] password 密码得分
    84  * 
    eturn 密码等级
    85  */
    86 PasswordLevel GetPasswordLevel(int score);
    87 
    88 
    89 #endif // CHECKPASS_H_INCLUDED
    checkPass.h
      1 #include "checkPass.h"
      2 
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <ctype.h>
      6 
      7 /** 强度评价*/
      8 const char *g_pPasswordLevel[]= {
      9     "很弱",
     10     "",
     11     "一般",
     12     "",
     13     "",
     14     "很强"
     15 };
     16 
     17 /**
     18 * defgroup prototypes
     19 * @{
     20 */
     21 
     22 /**
     23 * rief 负责调用其他计算函数,填充了长度字段
     24 * param[in] password 密码
     25 * param[out] rp 待填充的规则参数结构指针
     26 */
     27 void beginProcess(const char *password,RuleParameter *rp);
     28 
     29 /**
     30 * rief 填充大写、小写、数字、符号及他们的连续值字段
     31 * param[in] password 密码
     32 * param[out] rp 待填充的规则参数结构指针
     33 */
     34 void countNumbers(const char *password,RuleParameter *rp);
     35 
     36 /**
     37 * rief 填充连续递增/减字符的个数字段
     38 * param[in] password 密码
     39 * param[out] rp 待填充的规则参数结构指针
     40 */
     41 void countSeqNumbers(const char *password,RuleParameter *rp);
     42 
     43 /**
     44 * rief 填充重复单元字段
     45 * param[in] password 密码
     46 * param[out] rp 待填充的规则参数结构指针
     47 */
     48 void countRepeat(const char *password, RuleParameter *rp);
     49 
     50 /**
     51 * rief 计算密码得分
     52 * param[in] rp 已经填充的规则参数结构指针
     53 * 
    eturn 得分
     54 */
     55 int countScore(const RuleParameter *rp);
     56 
     57 /** @}*/
     58 
     59 PasswordLevel GetPasswordLevel(int score)
     60 {
     61     if(score<20) {
     62         return VERYWEEK;
     63     }
     64     if(score<40) {
     65         return WEEK;
     66     }
     67     if(score<60) {
     68         return AVERAGE;
     69     }
     70     if(score<80) {
     71         return STRONG;
     72     }
     73     return VERYSTRONG;
     74 }
     75 
     76 int GetPasswordScore(const char *password)
     77 {
     78     RuleParameter rp= {0};
     79     beginProcess(password,&rp);
     80     return countScore(&rp);
     81 }
     82 
     83 void beginProcess(const char *password,RuleParameter *rp)
     84 {
     85     if(password==NULL || rp==NULL) return;
     86 
     87     int i,j;
     88 
     89     char *pass_nospace=(char *)malloc(strlen(password)+1);
     90     char *pass_nospace_lower=(char *)malloc(strlen(password)+1);
     91 
     92     if(!pass_nospace) exit(EXIT_FAILURE);
     93 
     94     for(i=0,j=0; password[i]!=''; i++) {
     95         if(!isspace(password[i])) {
     96             pass_nospace[j]=password[i];
     97             pass_nospace_lower[j]=tolower(password[i]);
     98             ++j;
     99         }
    100     }
    101     pass_nospace[j]='';
    102 
    103     rp->nLength=strlen(pass_nospace);
    104 
    105     countRepeat(pass_nospace_lower,rp);
    106     countNumbers(pass_nospace,rp);
    107     countSeqNumbers(pass_nospace,rp);
    108 
    109     free(pass_nospace);
    110     free(pass_nospace_lower);
    111 }
    112 
    113 void countRepeat(const char *password, RuleParameter *rp)
    114 {
    115     if(!password || !rp)return;
    116 
    117     int i;
    118     for(i=0; i<rp->nLength; i++) {
    119         ++rp->RepeatChar[password[i]];
    120     }
    121 }
    122 
    123 void countNumbers(const char *password, RuleParameter *rp)
    124 {
    125     if(!password || !rp)return;
    126 
    127     int i;
    128     int last_upper_pos=-1;
    129     int last_lower_pos=-1;
    130     int last_digit_pos=-1;
    131 
    132     for(i=0; i<rp->nLength; i++) {
    133         if(isupper(password[i])) {
    134             if(last_upper_pos!=-1 && last_upper_pos+1==i) {
    135                 ++rp->nConsecUpper;
    136             }
    137             last_upper_pos=i;
    138             ++rp->nUpper;
    139         } else if(islower(password[i])) {
    140             if(last_lower_pos!=-1 && last_lower_pos+1==i) {
    141                 ++rp->nConsecLower;
    142             }
    143             last_lower_pos=i;
    144             ++rp->nLower;
    145         } else if(isdigit(password[i])) {
    146             if(last_digit_pos!=-1 && last_digit_pos+1==i) {
    147                 ++rp->nConsecDigit;
    148             }
    149             if(i>0 && i< rp->nLength-1) {
    150                 ++rp->nMidDigitSymbol;
    151             }
    152             last_digit_pos=i;
    153             ++rp->nDigit;
    154         } else {
    155             if(i>0 && i<rp->nLength-1) {
    156                 ++rp->nMidDigitSymbol;
    157             }
    158             ++rp->nSymbol;
    159         }
    160     }
    161 
    162     if(rp->nLower>0) ++rp->nRequirement;
    163     if(rp->nUpper>0) ++rp->nRequirement;
    164     if(rp->nDigit>0) ++rp->nRequirement;
    165     if(rp->nSymbol>0) ++rp->nRequirement;
    166 }
    167 
    168 /**
    169 * 
    ote 注意,此处计算重复数字的算法与参考链接处并不相同!
    170 *       经过反复测试,参考链接中测试算法与其描述并不相符,
    171 *       此处的实现中,字符不能同时被统计在上升序列和下降序列中!
    172 */
    173 void countSeqNumbers(const char *password,RuleParameter *rp)
    174 {
    175     if(!password || !rp || rp->nLength<3)return;
    176 
    177     int inc_count=1;
    178     int dec_count=1;
    179     int i=1;
    180 
    181     for(; i<rp->nLength; i++) {
    182         if(isalnum(password[i]) && isalnum(password[i-1])) {
    183             if(password[i]-password[i-1]==1) {
    184                 if(dec_count<3)++inc_count;
    185                 dec_count=1;
    186             } else if(password[i]-password[i-1]==-1) {
    187                 if(inc_count<3)++dec_count;
    188                 inc_count=1;
    189             } else {
    190                 inc_count=dec_count=1;
    191             }
    192         } else {
    193             inc_count=dec_count=1;
    194         }
    195 
    196         if(inc_count>=3 || dec_count>=3) {
    197             ++rp->nSequence;
    198         }
    199     }
    200 }
    201 
    202 int countScore(const RuleParameter *rp)
    203 {
    204     if(!rp || rp->nLength==0)return 0;
    205 
    206     int score=0;
    207     int i;
    208     int n;
    209 
    210     score+=rp->nLength * 4;
    211     if(rp->nUpper!=0)score+=(rp->nLength - rp->nUpper) *2;
    212     if(rp->nLower!=0)score+=(rp->nLength - rp->nLower) *2;
    213     if(rp->nLength!=rp->nDigit)score+=rp->nDigit *4;
    214     score+=rp->nSymbol *6;
    215     score+=rp->nMidDigitSymbol *2;
    216     if(rp->nLength>=8 && rp->nRequirement>=3) {
    217         score+=(rp->nRequirement+1)*2;
    218     }
    219 
    220     if(rp->nDigit==rp->nLength || rp->nLower+rp->nUpper==rp->nLength)
    221         score-=rp->nLength;
    222 
    223     for(i=0; i<CHARNUM; ++i) {
    224         n=rp->RepeatChar[i];
    225         if(n>1) {
    226             score-=n*(n-1);
    227         }
    228     }
    229     score-=rp->nConsecDigit * 2;
    230     score-=rp->nConsecLower *2;
    231     score-=rp->nConsecUpper *2;
    232     score-=rp->nSequence *3;
    233 
    234     if(score<0) score=0;
    235     if(score>100) score=100;
    236     return score;
    237 }
    checkPass.c
     1 #include <stdio.h>
     2 #include "checkPass.h"
     3 
     4 /**缓冲区最大长度*/
     5 # define BUFFERLEN 1000
     6 
     7 int main()
     8 {
     9     char password[BUFFERLEN];
    10     int score;
    11     PasswordLevel level;
    12 
    13     while(1) {
    14         printf("请输入密码:
    ");
    15         if(fgets(password,BUFFERLEN,stdin)==NULL)continue;
    16 
    17         score=GetPasswordScore(password);
    18         level=GetPasswordLevel(score);
    19 
    20         printf("该密码得分为 %d, 评价为 %s
    ",score,g_pPasswordLevel[level]);
    21     }
    22     return 0;
    23 }
    main.c
  • 相关阅读:
    poj 3321 Apple Tree
    hdu 1520 Anniversary party
    Light OJ 1089 Points in Segments (II)
    Timus 1018 Binary Apple Tree
    zoj 3299 Fall the Brick
    HFUT 1287 法默尔的农场
    Codeforces 159C String Manipulation 1.0
    GraphQL + React Apollo + React Hook 大型项目实战(32 个视频)
    使用 TypeScript & mocha & chai 写测试代码实战(17 个视频)
    GraphQL + React Apollo + React Hook + Express + Mongodb 大型前后端分离项目实战之后端(19 个视频)
  • 原文地址:https://www.cnblogs.com/livewithnorest/p/3152245.html
Copyright © 2011-2022 走看看