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
  • 相关阅读:
    USACO 之 Section 2.2 (已解决)
    USACO 之 Section 2.1 (已解决)
    《C++ Primer》学习 之 函数指针相关用法
    《C++ Primer》学习 之 const_cast使用
    《C++ Primer》学习 之 返回数组的引用(返回数组的指针,方法与之相同)
    USACO 之 Section 1.5 (已解决)
    USACO 之 Section 1.4 More Search Techniques (已解决)
    [NN] 对于BackPropagation(BP, 误差反向传播)的一些理解
    [CLPR] 定位算法探幽
    [LeetCode系列] 双单链表共同节点搜索问题
  • 原文地址:https://www.cnblogs.com/livewithnorest/p/3152245.html
Copyright © 2011-2022 走看看