一个玩具程序——测试密码强度(pure C)
替人写的C语言作业…
介绍:
程序名称:
密码强度检测程序
注释风格:
doxygen
测试环境:
linux3.6, gcc4.7
window7, vs2012
已知问题:
1. 算法与参考链接不一致,结果会有差别,详见代码注释。
2. 在vs下可能会编译不通过,将后缀改为cpp就可以了。vs的C编译器实现对C90支持不佳,gcc4.5以上可以正常编译通过。
#ifndef CHECKPASS_H_INCLUDED
#define CHECKPASS_H_INCLUDED /*!
* \brief 本程序用于检测密码强度
* \details 请根据提示输入密码,程序会自动输出对应的强度
*
* 程序会根据是否满足一定的条件对密码进行打分,然后区分出档次。
* 得分最低0分,最高100分;等级分为很弱-弱-一般-好-强-极强几个档次。
* 判断标准(参考[链接](http://goo.gl/wuQdN):
* 1. 最低要求包括
* * 长度>8位
* * 以下四种元素至少有三种:
* - 大写英文字母
* - 小写英文字母
* - 数字
* - 特殊符号
* 2. 加分条件
* * 密码总字数 +(次数*4)
* * 大写字母数 +(长度-字数)*2 [字数必须>0]
* * 小写字母数 +(长度-字数)*2 [同上]
* * 数字个数 +(次数*4)
* * 特殊符号数 +(次数*6)
* * 数字或符号出现在密码中间部分 +(次数*2)
* * 达到最低需求 +(次数*2)
* 3. 减分条件
* * 只有字母 -次数
* * 只有数字 -次数
* * 出现重复单元,对每个重复的字符 -次数*(次数-1) [不计大小写]
* * 连续大写字母 -次数*2
* * 连续小写字母 -次数*2
* * 连续多个数字 -次数*2
* * 字母顺序递增/减(三个及以上) -次数*3
* * 数字顺序递增/减(三个及以上) -次数*3
*
* \author
* \date 2013-06-22
* \copyright GNU Public License
*/ /** 字符数目,取char的最大值+1*/
#define CHARNUM 256 /** 强度评价*/
extern const char *g_pPasswordLevel[]; /** 强度枚举*/
typedef enum _PasswordLevel {
VERYWEEK,
WEEK,
AVERAGE,
GOOD,
STRONG,
VERYSTRONG
} PasswordLevel; /** 计算得分需要的参数*/
typedef struct _RuleParameter {
int nLength; ///< 密码长度
int nUpper; ///< 大写字母个数
int nLower; ///< 小写字母个数
int nDigit; ///< 数字个数
int nSymbol; ///< 特殊字符个数
int nMidDigitSymbol; ///< 中间部分的数字或字符个数
int nRequirement; ///< 达到最低需求的次数
int RepeatChar[CHARNUM]; ///< 每个字符重复的次数
int nConsecUpper; ///< 连续大写字母个数
int nConsecLower; ///< 连续小写字母个数
int nConsecDigit; ///< 连续数字个数
int nSequence; ///< (三个及以上)顺序字母/数字次数
} RuleParameter; /**
* \brief 求密码得分
* \param[in] password 密码
* \return 得分
*/
int GetPasswordScore(const char *password); /**
* \brief 求密码等级
* \param[in] password 密码得分
* \return 密码等级
*/
PasswordLevel GetPasswordLevel(int score); #endif // CHECKPASS_H_INCLUDED
checkPass.h
#include "checkPass.h" #include <stdlib.h>
#include <string.h>
#include <ctype.h> /** 强度评价*/
const char *g_pPasswordLevel[]= {
"很弱",
"弱",
"一般",
"好",
"强",
"很强"
}; /**
* \defgroup prototypes
* @{
*/ /**
* \brief 负责调用其他计算函数,填充了长度字段
* \param[in] password 密码
* \param[out] rp 待填充的规则参数结构指针
*/
void beginProcess(const char *password,RuleParameter *rp); /**
* \brief 填充大写、小写、数字、符号及他们的连续值字段
* \param[in] password 密码
* \param[out] rp 待填充的规则参数结构指针
*/
void countNumbers(const char *password,RuleParameter *rp); /**
* \brief 填充连续递增/减字符的个数字段
* \param[in] password 密码
* \param[out] rp 待填充的规则参数结构指针
*/
void countSeqNumbers(const char *password,RuleParameter *rp); /**
* \brief 填充重复单元字段
* \param[in] password 密码
* \param[out] rp 待填充的规则参数结构指针
*/
void countRepeat(const char *password, RuleParameter *rp); /**
* \brief 计算密码得分
* \param[in] rp 已经填充的规则参数结构指针
* \return 得分
*/
int countScore(const RuleParameter *rp); /** @}*/ PasswordLevel GetPasswordLevel(int score)
{
if(score<) {
return VERYWEEK;
}
if(score<) {
return WEEK;
}
if(score<) {
return AVERAGE;
}
if(score<) {
return STRONG;
}
return VERYSTRONG;
} int GetPasswordScore(const char *password)
{
RuleParameter rp= {};
beginProcess(password,&rp);
return countScore(&rp);
} void beginProcess(const char *password,RuleParameter *rp)
{
if(password==NULL || rp==NULL) return; int i,j; char *pass_nospace=(char *)malloc(strlen(password)+);
char *pass_nospace_lower=(char *)malloc(strlen(password)+); if(!pass_nospace) exit(EXIT_FAILURE); for(i=,j=; password[i]!='\0'; i++) {
if(!isspace(password[i])) {
pass_nospace[j]=password[i];
pass_nospace_lower[j]=tolower(password[i]);
++j;
}
}
pass_nospace[j]='\0'; rp->nLength=strlen(pass_nospace); countRepeat(pass_nospace_lower,rp);
countNumbers(pass_nospace,rp);
countSeqNumbers(pass_nospace,rp); free(pass_nospace);
free(pass_nospace_lower);
} void countRepeat(const char *password, RuleParameter *rp)
{
if(!password || !rp)return; int i;
for(i=; i<rp->nLength; i++) {
++rp->RepeatChar[password[i]];
}
} void countNumbers(const char *password, RuleParameter *rp)
{
if(!password || !rp)return; int i;
int last_upper_pos=-;
int last_lower_pos=-;
int last_digit_pos=-; for(i=; i<rp->nLength; i++) {
if(isupper(password[i])) {
if(last_upper_pos!=- && last_upper_pos+==i) {
++rp->nConsecUpper;
}
last_upper_pos=i;
++rp->nUpper;
} else if(islower(password[i])) {
if(last_lower_pos!=- && last_lower_pos+==i) {
++rp->nConsecLower;
}
last_lower_pos=i;
++rp->nLower;
} else if(isdigit(password[i])) {
if(last_digit_pos!=- && last_digit_pos+==i) {
++rp->nConsecDigit;
}
if(i> && i< rp->nLength-) {
++rp->nMidDigitSymbol;
}
last_digit_pos=i;
++rp->nDigit;
} else {
if(i> && i<rp->nLength-) {
++rp->nMidDigitSymbol;
}
++rp->nSymbol;
}
} if(rp->nLower>) ++rp->nRequirement;
if(rp->nUpper>) ++rp->nRequirement;
if(rp->nDigit>) ++rp->nRequirement;
if(rp->nSymbol>) ++rp->nRequirement;
} /**
* \note 注意,此处计算重复数字的算法与参考链接处并不相同!
* 经过反复测试,参考链接中测试算法与其描述并不相符,
* 此处的实现中,字符不能同时被统计在上升序列和下降序列中!
*/
void countSeqNumbers(const char *password,RuleParameter *rp)
{
if(!password || !rp || rp->nLength<)return; int inc_count=;
int dec_count=;
int i=; for(; i<rp->nLength; i++) {
if(isalnum(password[i]) && isalnum(password[i-])) {
if(password[i]-password[i-]==) {
if(dec_count<)++inc_count;
dec_count=;
} else if(password[i]-password[i-]==-) {
if(inc_count<)++dec_count;
inc_count=;
} else {
inc_count=dec_count=;
}
} else {
inc_count=dec_count=;
} if(inc_count>= || dec_count>=) {
++rp->nSequence;
}
}
} int countScore(const RuleParameter *rp)
{
if(!rp || rp->nLength==)return ; int score=;
int i;
int n; score+=rp->nLength * ;
if(rp->nUpper!=)score+=(rp->nLength - rp->nUpper) *;
if(rp->nLower!=)score+=(rp->nLength - rp->nLower) *;
if(rp->nLength!=rp->nDigit)score+=rp->nDigit *;
score+=rp->nSymbol *;
score+=rp->nMidDigitSymbol *;
if(rp->nLength>= && rp->nRequirement>=) {
score+=(rp->nRequirement+)*;
} if(rp->nDigit==rp->nLength || rp->nLower+rp->nUpper==rp->nLength)
score-=rp->nLength; for(i=; i<CHARNUM; ++i) {
n=rp->RepeatChar[i];
if(n>) {
score-=n*(n-);
}
}
score-=rp->nConsecDigit * ;
score-=rp->nConsecLower *;
score-=rp->nConsecUpper *;
score-=rp->nSequence *; if(score<) score=;
if(score>) score=;
return score;
}
checkPass.c
#include <stdio.h>
#include "checkPass.h" /**缓冲区最大长度*/
# define BUFFERLEN int main()
{
char password[BUFFERLEN];
int score;
PasswordLevel level; while() {
printf("请输入密码:\n");
if(fgets(password,BUFFERLEN,stdin)==NULL)continue; score=GetPasswordScore(password);
level=GetPasswordLevel(score); printf("该密码得分为 %d, 评价为 %s\n",score,g_pPasswordLevel[level]);
}
return ;
}
main.c
一个玩具程序——测试密码强度(pure C)的更多相关文章
- 使用jQuery开发一个带有密码强度检验的超酷注册页面
在今天的jQuery教程中,我们将介绍如何使用jQuery和其它相关的插件来生成一个漂亮的带有密码强度检验的注册页面,希望大家喜欢! 相关的插件和类库 complexify - 一个密码强度检验jQu ...
- 利用JavaScript来实现用动态检验密码强度
平时我们会在某些网站的注册页面或者更改密码的页面发现当我们输入密码时,会有一个类似于进度条的长条进行提示用户输入的密码强度.如下图: 我看到有些人用几张不同的图片来替换,这样似乎可以,但是不太好.所以 ...
- 自己动手搭建 Redis 环境,并建立一个 .NET HelloWorld 程序测试
关于 Redis ,下面来自百度百科: redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set( ...
- 自己动手搭建 Redis 环境,并建立一个 .NET HelloWorld 程序测试(转)
关于 Redis ,下面来自百度百科: redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set( ...
- Selenium也是一个用于Web应用程序测试的工具
Selenium也是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包括IE.Mozilla Firefox.Mozilla Suite ...
- C++实现密码强度测试
最近在博客中看到许多用js写的密码强度检测,我觉得挺有意思的,所以呢我打算自己也写个来玩玩,最可悲的是我还没学js,当然这不重要,所以呢打算用C++来写一个密码强度检测,这里我来给大家说说用JS写的和 ...
- js测试密码的强度
测试密码的强度.js //网站也会根据输入密码的字符特点给出相应的提示,如密码过短.强度差.强度中等.强度强等. //这又是怎么实现的呢?看下面代码: <input type="pas ...
- 实例--post请求,完成一个抽奖程序概率的测试
一个web项目测试,测试抽奖概率的正确性,写了一个小代码,验证概率 post和get请求的一个工具类 package kankan_interface; import java.io.IOExcept ...
- Js判断密码强度并显示提示信息
用javascipt实现的Ajax判断密码强弱的功能,大多数有用户注册功能的网站,都会有这么一个功能,作为WEB程序员,应该会写这种小模块哦,不懂的就看下这个例子,觉得挺简单,当初帮助了不少人学会了密 ...
随机推荐
- go与json
Go语言对JSON进行编码和解码 http://outofmemory.cn/code-snippet/3766/Go-language-to-JSON-to-coding-jiema package ...
- hadoop多机安装HA+YARN
HA 相比于Hadoop1.0,Hadoop 2.0中的HDFS增加了两个重大特性,HA(热备)和Federation(联邦).HA即为High Availability,用于解决NameNode单点 ...
- C#功能扩张方式
有时候,为了完成一些window的一些操作,需要引入一些dll进行操作 1) 引入系统api进行操作,形如[DllImport("urlmon.dll", CharSet = C ...
- Linux下压缩某个文件夹(文件夹打包)
tar -zcvf /home/xahot.tar.gz /xahottar -zcvf 打包后生成的文件名全路径 要打包的目录例子:把/xahot文件夹打包后生成一个/home/xahot.tar. ...
- Linux本地无法登录,远程却可以登录
[root@oraserver ~]# vi /etc/pam.d/login 将以下内容注释掉: #session required /lib/security/pam_limits. ...
- POJ_3176_Cow_Bowling_(数字三角形)_(动态规划)
描述 http://poj.org/problem?id=3176 给出一个三角形,每个点可以走到它下面两个点,将所有经过的点的值加起来,问最大的和是多少. Cow Bowling Time Limi ...
- c语言开源项目--SQLite学习资料总结
同行博客: 1.http://www.cnblogs.com/hustcat/category/175618.html; 2.http://blog.csdn.net/zhoudaxia/articl ...
- Excel通过宏创建百万数据
打开视图->宏->编辑,代码如下,cells(n,m)表示当前Excel表格第n行第m列</span> Sub newdata() Dim i As Long Cells(i, ...
- [洛谷U990]传递游戏(90分)
[题目描述 Description] n个人在做传递物品的游戏,编号为1-n. 游戏规则是这样的:开始时物品可以在任意一人手上,他可把物品传递给其他人中的任意一位:下一个人可以传递给未接过物品的任意一 ...
- CSS样式学习笔记『W3School』
1.选择器+声明声明:属性+值eg:h1{color:red;font-size:14px;}颜色:p{color:#ff0000;}p{color:#f00;}p{color:rgb(255,0,0 ...