弱口令的基本校验包括:口令字符串长度校验、口令字符串包含的字符类型校验、口令字符串包含的不同字符数校验。
口令字符串长度校验:验证口令字符串的长度不能低于规定值(如6)。
口令字符串包含的字符类型校验:把字符类型分为大写字母、小写字母、数组、特殊字符四类,校验口令字符串包含的字符类型不能低于规定值(如2)。
口令字符串包含的不同字符数校验:不区分大、小写时a与A算同一字符,区分大、小写时a与A为不同字符。校验口令字符串中包含的不同字符数不能低于规定值(如4)。
弱口令的高级校验包括:连续字符校验、键盘输入规则校验、弱口令字典校验。
连续字符校验:校验口令字符串中连续字符组成的子串长度不但能高于规定的值(如40%)。
键盘输入规则校验:详细见2.1.3
弱口令字典校验:在弱口令字典中校验该口令字符串是否为弱口令。
结合笔记本电脑和台式电脑键盘的布局规则,将字符输入键映射为4*10的二维数组矩阵(1-0,q-p,a-;,z-?),把密码字符串中每各字符格式化为键盘矩阵中对应的坐标,判断连续字符的坐标是否相邻,并记录连续相邻的串长度进行安全性评估
1:判断密码是否为null或空,如果不是进入下一步,否则返回结果(密码安全性不符合)
2:判断密码字符串长度是否符合要求,默认是大于等于6位,如果是进入下一步,否则返回结果(密码安全性不符合)
3:循环取出密码串中从0位置到长度下限++的子串,进行下面4到8的操作并记录结果到一个double[]中
4:评估密码中包含的字符类型是否符合要求,如果低于下限返回0,否则返回6-10的double
5:评估密码至少包含的不同字符数(不区分大、小写),返回int,如果字符数小于下限返回0,否则返回6-10的double
6:评估密码字符串是否包含a-z,z-a这样的连续字符,返回一个double,如果连续字符占整个串长度的40%以上返回0,否则返回(1-连续字符占整个串长度的百分比) * 10
7:评估密码字符串是否匹配键盘输入习惯,返回0-10的整数,值越大表示越不符合键盘输入习惯
8:根据3、4、5、6的评估结果综合评估出密码的安全评估值(0-10的double)
9:循环3中double[]的值,如果全是0返回0,否则从第一个不是0的位置开始累加,如果后一个位置为0则加长度修正值1,如果累加结果大于10,循环结束返回10
10:判断7产生的安全评估值是否大于安全评估值的下限(默认7),是返回true,否则返回false
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.log4j.Logger;
/**
* <strong>Title : CheckPWD</strong><br>
* <strong>Description : 密码强度验证</strong><br>
* <strong>Create on : Dec 6, 2011 7:34:45 PM</strong><br>
* @author liulang@mochasoft.com.cn<br>
* @version v1.0<br>
* <br>
* 详细验证步骤说明:<br>
* 1:判断密码是否为null或空,如果不是进入下一步,否则返回结果(密码安全性不符合)<br>
* 2:判断密码字符串长度是否符合要求,默认是大于等于6位,如果是进入下一步,否则返回结果(密码安全性不符合)<br>
* 3:循环取出密码串中从0位置到长度下限++的子串,进行下面4到8的操作并记录结果到一个double[]中
* 4:评估密码中包含的字符类型是否符合要求,如果低于下限返回0,否则返回6-10的double<br>
* 5:评估密码至少包含的不同字符数(不区分大、小写),返回int,如果字符数小于下限返回0,否则返回6-10的double<br>
* 6:评估密码字符串是否包含a-z,z-a这样的连续字符,返回一个double,如果连续字符占整个串长度的40%以上返回0,否则返回(1-连续字符占整个串长度的百分比) * 10<br>
* 7:评估密码字符串是否匹配键盘输入习惯,返回0-10的整数,值越大表示越不符合键盘输入习惯<br>
* 8:根据3、4、5、6的评估结果综合评估出密码的安全评估值(0-10的double)<br>
* 9:循环3中double[]的值,如果全是0返回0,否则从第一个不是0的位置开始累加,如果后一个位置为0则加长度修正值1,如果累加结果大于10,循环结束返回10<br>
* 9:判断7产生的安全评估值是否大于安全评估值的下限(默认7),是返回true,否则返回false
* <br>
* <strong>修改历史:</strong><br>
* 修改人-------------修改日期-------------修改描述<br>
* --------------------------------------------<br>
* liulang-----------2011/12/7---------<br>
* 1:增加容错处理;<br>
* 2:修改键盘输入习惯匹配评估算法的逻辑;<br>
* 3:增加一个更加严格的键盘习惯匹配算法maches2(可匹配类似1z2x3c4v5b这样的特殊字符串)<br>
* <br>
*/
public final class CheckPWD {
private static Logger logger = Logger.getLogger(CheckPWD.class);
/**
* 安全密码评估值的下限,取值范围:0-10,默认:7
*/
public static double PASSWORD_STRONG = 7;
/**
* 密码字符串包含的字符类型(a-z,A-Z,0-9,特殊字符)在密码安全性评估中所占比例,默认:0.15
*/
public static double CHAR_TYPE_NUM_THRESHOLD = 0.15;
/**
* 密码字符串包含的不同字符数(不区分大、小写,同一键位的视为同一字符)在密码安全性评估中所占比例,默认:0.35
*/
public static double MIN_CONTAIN_CHAR_NUM_THRESHOLD = 0.35;
/**
* 密码字符串匹配键盘输入习惯在密码安全性评估中所占比例,默认:0.3
*/
public static double KEYSET_MATCHER_THRESHOLD = 0.3;
/**
* 评估密码字符串中a-z,z-a这样的连续字符在密码安全性评估中所占比例,默认:0.2
*/
public static double SEQUENTIAL_CHARS_THRESHOLD = 0.2;
/**
* 键盘输入习惯匹配规则严格模式
*/
public static int KEYSET_MATCHER_STRICT_MODE = 1;
/**
* 键盘输入习惯匹配规则不严格模式
*/
public static int KEYSET_MATCHER_UNDEMANDING_MODE = 0;
/**
* 密码最小长度,默认为6
*/
private static int MIN_LENGTH = 6;
/**
* 密码至少包含的不同字符数(不区分大、小写),(例如:"aaa"包含一个字符,"aba"包含2个字符,"aA"包含1个字符等),默认为4
*/
private static int MIN_CONTAIN_CHAR_NUM = 4;
/**
* 密码至少包含的字符类型数(a-z,A-Z,0-9,特殊字符),默认为2
*/
private static int MIN_CHAR_TYPE_NUM = 2;
/**
* 中等强度密码键盘规则匹配严格度,默认0.6
*/
private static double THRESHOLD_MEDIUM = 0.6;
/**
* 高安全度密码键盘规则匹配严格度,默认0.4
*/
private static double THRESHOLD_STRONG = 0.4;
/**
* 高安全度密码键盘规则匹配严格度,默认0.4
*/
private static double MAX_SEQUENTIAL_CHARS_THRESHOLD = 0.4;
/**
* 字母顺序A-Z
*/
private static String A_Z = "abcdefghijklmnopqrstuvwxyz";
/**
* 字母顺序Z-A
*/
private static String Z_A = "zyxwvutsrqponmlkjihgfedcba";
/**
* shift键产生的字符与非shift键时对应的字符
*/
private static Map CONVERSION_MAP = new HashMap();
/**
* 将键盘按键格式话为4*10的矩阵的坐标
*/
private static Map DICTIONARY_MAP = new HashMap();
private static String[] dictionary1 = "1 2 3 4 5 6 7 8 9 0".split("\\s+");
private static String[] dictionary2 = "q w e r t y u i o p".split("\\s+");
private static String[] dictionary3 = "a s d f g h j k l ;".split("\\s+");
private static String[] dictionary4 = "z x c v b n m , . /".split("\\s+");
private static String[][] DICTIONARY_MATRIX = {dictionary1, dictionary2, dictionary3, dictionary4};
static {
CONVERSION_MAP.put("!", "1");
CONVERSION_MAP.put("@", "2");
CONVERSION_MAP.put("#", "3");
CONVERSION_MAP.put("$", "4");
CONVERSION_MAP.put("%", "5");
CONVERSION_MAP.put("^", "6");
CONVERSION_MAP.put("&", "7");
CONVERSION_MAP.put("*", "8");
CONVERSION_MAP.put("(", "9");
CONVERSION_MAP.put(")", "0");
CONVERSION_MAP.put(":", ";");
CONVERSION_MAP.put("<", ",");
CONVERSION_MAP.put(">", ".");
CONVERSION_MAP.put("?", "/");
for(int i=0, ln=DICTIONARY_MATRIX.length; i<ln; i++) {
String[] dic = DICTIONARY_MATRIX[i];
for(int j=0, lnt=dic.length; j<lnt; j++) {
int[] row_cell = {i,j};
DICTIONARY_MAP.put(dic[j], row_cell);
}
}
}
private CheckPWD(){
}
/**
* 严格的键盘输入习惯匹配规则,匹配连续或者非连续的(可以匹配:1a2s3d4f5g这样的有规律的串),比matches方法的匹配规则更严格
* @param matcherList
* @param row_cellList
* @param index
*/
private static void maches2(List matcherList, List row_cellList, int index) {
for(; index<row_cellList.size(); index++) {
int[] row_cell_t = (int[]) row_cellList.get(index);
if(row_cell_t != null) {
boolean flag = true;
for(int i=0; i<matcherList.size(); i++) {
List list = (List) matcherList.get(i);
for(int j=0; j<list.size(); j++) {
int[] row_cell = (int[]) list.get(j);
if(((Math.abs(row_cell_t[0] - row_cell[0]) <= 1) && (Math.abs(row_cell_t[1] - row_cell[1]) <= 1))) {
list.add(row_cell_t);
flag = false;
break;
}
}
if(!flag) break;
}
if(flag) {
List arrt = new ArrayList();
arrt.add(row_cell_t);
matcherList.add(arrt);
}
}
}
}
/**
* 键盘输入习惯匹配规则,匹配连续输入(不能匹配:1a2s3d4f5g这样的有规律的串),比maches2方法的匹配规则宽松
* @param matcherList
* @param row_cellList
* @param index
*/
private static void matches(List matcherList, List row_cellList, int index) {
for(int i=0; i<matcherList.size(); i++) {
List list = (List) matcherList.get(i);
for(int ln=row_cellList.size(); index<ln; index++) {
int[] row_cell = (int[]) list.get(list.size()-1);
int[] row_cell_t = (int[]) row_cellList.get(index);
//如果相邻的键盘字符(某一个键的左右、上下、斜向相邻)被连续输入,在原匹配链条上增加新的输入
if((row_cell != null) && (row_cell_t != null) &&
((Math.abs(row_cell_t[0] - row_cell[0]) <= 1) && (Math.abs(row_cell_t[1] - row_cell[1]) <= 1))) {
list.add(row_cell_t);
}else { //如果新字符和上一匹配链条的结尾字符距离较远,这结束上一匹配链条,以该字符为首增加新的匹配链条
List arrt = new ArrayList();
arrt.add(row_cell_t);
matcherList.add(arrt);
index++;
break;
}
}
}
}
/**
* 键盘规则匹配器,返回double
* @param password 密码字符串
* @return
*/
public static double keysetMatcher(String password, int matchesMode) {
String t_password = new String(password);
t_password = t_password.toLowerCase();
t_password = canonicalizeWord(password);
logger.debug("****************将密码字符串转换为键盘矩阵的对应坐标 start******************");
char[] pwdCharArr = t_password.toCharArray();
List row_cellList = new ArrayList();
int Num = 0;
int startIndex = -1;
for(int i=0, ln= pwdCharArr.length; i<ln; i++) {
int[] row_cell = (int[]) DICTIONARY_MAP.get(String.valueOf(pwdCharArr[i]));
if(row_cell != null) {
row_cellList.add(row_cell);
Num++;
if(startIndex == -1) startIndex = i;
} else row_cellList.add(null);
}
logger.debug("****************将密码字符串转换为键盘矩阵的对应坐标 end******************");
logger.debug("****************初始化匹配链条 start******************");
int index = startIndex+1;
int[] row_cell0 = (int[]) row_cellList.get(startIndex);
List matcherList = new ArrayList();
List arr0 = new ArrayList();
arr0.add(row_cell0);
matcherList.add(arr0);
logger.debug("****************初始化匹配链条 end******************");
//根据匹配规则进行匹配
if(KEYSET_MATCHER_UNDEMANDING_MODE == matchesMode) matches(matcherList, row_cellList, index); //不严格的匹配模式
else if(KEYSET_MATCHER_STRICT_MODE == matchesMode) maches2(matcherList, row_cellList, index); //严格的匹配模式
double rValue = 0;
for(double threshold = THRESHOLD_STRONG; threshold <= THRESHOLD_MEDIUM; threshold+=0.1) {
boolean flag = true;
int nMinimumMeaningfulMatchLength = (int) (Num * threshold);
//特殊字符(~ ` - _ = + [ { ] } \ | ' ")所占比率上限
if(threshold <= ((t_password.length() - Num)*1.0/t_password.length())) flag = false;
if(flag) {
for(int i=0; i<matcherList.size(); i++) {
List list = (List) matcherList.get(i);
if(list.size() >= nMinimumMeaningfulMatchLength) {
flag = false;
return rValue;
}
}
}
if(flag) {
if(THRESHOLD_MEDIUM == THRESHOLD_STRONG) rValue = 10;
else rValue = 6 + 4*(THRESHOLD_MEDIUM-threshold)*1.0/(THRESHOLD_MEDIUM-THRESHOLD_STRONG);
break;
}
}
return rValue;
}
/**
* 替换密码中的shift键产生的字符转换为非shift键时对应的字符
* @param password 密码字符串
* @return 替换后的密码字符串
*/
private static String canonicalizeWord(String password) {
StringBuffer sb = new StringBuffer();
if(password != null && password.length() > 0) {
for(int i=0; i<password.length(); i++) {
String cs = String.valueOf(password.charAt(i));
if(CONVERSION_MAP.get(cs) != null) sb.append(CONVERSION_MAP.get(cs));
else sb.append(cs);
}
}
return sb.toString();
}
/**
* 搜索字符str中是否包含有regex指定的正则表达式匹配的子串
* @param str 待搜索字符串
* @param regex 正则表达式字符串
* @return 包含匹配子串返回true,否则返回false
*/
private static boolean stringFind(String str, String regex) {
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
if(m.find()) return true;
return false;
}
/**
* 评估密码中包含的字符类型是否符合要求,如果低于下限返回0,否则返回6 + (字符类型总数 - 下限) * 2
* @param password 密码字符串
* @param num 密码至少包含的字符类型数(a-z,A-Z,0-9,特殊字符),默认为2
* @return
*/
public static double checkCharTypeNum(String password, int num) {
int typeNum = 0;
if(stringFind(password, "[a-z]+")) typeNum++;
if(stringFind(password, "[0-9]+")) typeNum++;
if(stringFind(password, "[A-Z]+")) typeNum++;
if(stringFind(password, "\\p{Punct}+")) typeNum++;
double rValue = 0;
if(typeNum >= num) {
if(num == 4) rValue = 10;
else rValue = 6 + (typeNum - num)*1.0/(4-num) * 4;
}
return rValue;
}
/**
* 评估a-z,z-a这样的连续字符,返回一个double,如果连续字符占整个串长度的40%以上返回0,否则返回(1-连续字符占整个串长度的百分比) * 10
* @param password
* @return
*/
public static double checkSequentialChars(String password) {
String t_password = new String(password);
t_password = t_password.toLowerCase();
double rValue = 0;
int i = 2;
int n = t_password.length();
for(; i<n; i++) {
boolean flag = true;
for(int j=0; j+i<n; j++) {
String str = t_password.substring(j, j+i);
if((A_Z.indexOf(str) != -1) || (Z_A.indexOf(str) != -1)) {
flag = false;
break;
}
}
if(flag) {
if(i*1.0/n > MAX_SEQUENTIAL_CHARS_THRESHOLD) rValue = 0;
else rValue = (1-i*1.0/n) * 10;
break;
}
}
return rValue;
}
/**
* 评估密码至少包含的不同字符数(不区分大、小写),返回int,如果字符数小于下限返回0,否则返回6 + (包含字符数 - 下限),如果大于10,返回10
* @param password 密码字符串
* @param num 密码至少包含的字符类型数(a-z,A-Z,0-9,特殊字符),默认为2
* @return
*/
public static double checkMinContainCharNum(String password, int num) {
String t_password = new String(password);
// t_password = t_password.replaceAll("(.)\\1+", "$1");
t_password = t_password.toLowerCase();
t_password = canonicalizeWord(password);
Map map = new HashMap();
int snum = 0;
for(int i=0,ln= t_password.length(); i<ln; i++) {
String cs = String.valueOf(t_password.charAt(i));
if(map.get(cs) == null) {
map.put(cs, cs);
snum++;
}
}
double rValue = 0;
if(snum >= num) rValue = 6 + (snum - num);
return (rValue > 10 ? 10 : rValue);
}
/**
* 评估密码强度,根据密码长度,包含的字符类型,包含不同字符数,包含的连续字符,键盘输入习惯综合评估密码强度,返回0-10的double
* @param password
* @return
*/
public static double evalPWD(String password, int matchesMode) {
if(password == null || "".equals(password.replaceAll("\\s+", ""))) return 0; //判断密码为null或""
if(MIN_LENGTH > password.length()) return 0; //判断密码长度是否符合
double[] val = new double[1000];
int n = 0;
for(int i=MIN_LENGTH; i<=password.length(); i++) {
String t_password = password.substring(0, i);
//评估密码中包含的字符类型是否符合要求
double typeNumCheckResult = checkCharTypeNum(t_password,MIN_CHAR_TYPE_NUM);
//评估密码至少包含的不同字符数(不区分大、小写)
double minContainCharNumCheckResult = checkMinContainCharNum(t_password, MIN_CONTAIN_CHAR_NUM);
//评估a-z,z-a这样的连续字符
double sequentialCharsCheckResult = checkSequentialChars(t_password);
//评估键盘输入习惯
double keysetMatcherResult = keysetMatcher(t_password, matchesMode);
logger.debug("评估密码中包含的字符类型结果:"+typeNumCheckResult);
logger.debug("评估密码至少包含的不同字符数结果:"+minContainCharNumCheckResult);
logger.debug("评估a-z,z-a这样的连续字符结果:"+sequentialCharsCheckResult);
logger.debug("评估键盘输入习惯结果:"+keysetMatcherResult);
if(typeNumCheckResult == 0 || minContainCharNumCheckResult == 0 || sequentialCharsCheckResult == 0 || keysetMatcherResult == 0) {
val[n] = 0;
}else {
val[n] = typeNumCheckResult*CHAR_TYPE_NUM_THRESHOLD + minContainCharNumCheckResult*MIN_CONTAIN_CHAR_NUM_THRESHOLD +
sequentialCharsCheckResult*SEQUENTIAL_CHARS_THRESHOLD + keysetMatcherResult*KEYSET_MATCHER_THRESHOLD;
}
n++;
}
double rValue = 0;
boolean flag = false;
for(int i=0; i<n; i++) {
if(val[i] != 0) {
rValue += val[i];
flag = true;
}
if(flag && val[i] == 0) rValue += 1;
if(rValue >= 10) {
rValue = 10;
break;
}
}
return rValue;
// //评估密码中包含的字符类型是否符合要求
// double typeNumCheckResult = checkCharTypeNum(password,MIN_CHAR_TYPE_NUM);
// //评估密码至少包含的不同字符数(不区分大、小写)
// double minContainCharNumCheckResult = checkMinContainCharNum(password, MIN_CONTAIN_CHAR_NUM);
// //评估a-z,z-a这样的连续字符
// double sequentialCharsCheckResult = checkSequentialChars(password);
// //评估键盘输入习惯
// double keysetMatcherResult = keysetMatcher(password, matchesMode);
// logger.debug("评估密码中包含的字符类型结果:"+typeNumCheckResult);
// logger.debug("评估密码至少包含的不同字符数结果:"+minContainCharNumCheckResult);
// logger.debug("评估a-z,z-a这样的连续字符结果:"+sequentialCharsCheckResult);
// logger.debug("评估键盘输入习惯结果:"+keysetMatcherResult);
// if(typeNumCheckResult == 0 || minContainCharNumCheckResult == 0 || sequentialCharsCheckResult == 0 || keysetMatcherResult == 0) {
// return 0;
// }else {
// return typeNumCheckResult*CHAR_TYPE_NUM_THRESHOLD + minContainCharNumCheckResult*MIN_CONTAIN_CHAR_NUM_THRESHOLD +
// sequentialCharsCheckResult*SEQUENTIAL_CHARS_THRESHOLD + keysetMatcherResult*KEYSET_MATCHER_THRESHOLD;
// }
}
/**
* 用严格模式校验密码强度,根据密码评估结果判断密码是否可用,默认评估结果大于7的可用
* @param password
* @return
*/
public static boolean checkPwdInStrictMode(String password) {
double rValue = evalPWD(password, KEYSET_MATCHER_STRICT_MODE);
if(rValue >= PASSWORD_STRONG) return true;
return false;
}
/**
* 非严格模式校验密码强度,根据密码评估结果判断密码是否可用,默认评估结果大于7的可用
* @param password
* @return
*/
public static boolean checkPwdIndemandingMode(String password) {
double rValue = evalPWD(password, KEYSET_MATCHER_UNDEMANDING_MODE);
if(rValue >= PASSWORD_STRONG) return true;
return false;
}
public static void main(String[] args) {
String[] sArr = {
"1a2s3d4f5g6h",
"zcvjlufw123433546",
"~]sdfa^9mi|",
"`%0,uTs85vkj",
"liulanggood123",
"PASSword_123",
"yanghao1234",
"yanghao123",
"yanghao1981"
};
for(int i=0; i<sArr.length; i++) {
System.out.println("严格模式下校验"+sArr[i]+"的密码强度:"+evalPWD(sArr[i], KEYSET_MATCHER_STRICT_MODE));
System.out.println("非格模式下校验"+sArr[i]+"的密码强度:"+evalPWD(sArr[i], KEYSET_MATCHER_UNDEMANDING_MODE));
}
}
}
分享到:
相关推荐
基于口令的身份认证方案的设计与实现 概述: 随着互联网的飞速发展,全球性信息化浪潮也是日新月异的,信息网络技术也正日益普及和广泛应用,不断深入应用层次,同时从传统的小型业务系统,开始逐渐向大型关键业务...
总的来说,这篇毕业论文详细研究了基于时间算法的动态口令验证技术,探讨了其在网络安全领域的应用,旨在提供一种更安全、可靠的身份认证解决方案。通过深入分析和实证测试,论文为动态口令技术在不同规模企业的实际...
随着互联网的快速发展,身份认证成为保护用户信息安全的关键环节,其中口令验证是最基本且广泛应用的方法。然而,随着信息爆炸式增长,口令安全面临严重挑战。用户经常使用弱口令、个人信息构建易记密码,甚至在多个...
#### 四、基于验证元的三方口令认证密钥交换协议的设计 近年来,研究人员已经开始探索基于验证元的3PAKE协议,特别是在后量子时代背景下。2021年,舒琴等人提出了首个基于格上的基于验证元的3PAKE协议。该协议在...
1. 设计一次性口令的算法: Lamport 方案、时间同步方案、挑战/应答方案等。 2. 使用 C++ 语言编写一个一次性口令的程序,实现用户注册、身份认证、口令计算和退出等功能。 3. 建立相当的系统安全性,包括登录用户...
#### 基于二维条码的一次性口令认证方案设计 本文提出的认证方案充分利用了二维条码的优势,结合OTP技术,设计了一种既安全又便捷的认证机制。具体来说,方案包括以下几个关键步骤: 1. **初始化阶段**:用户在...
该方案使用USB-Key进行用户口令的验证并存储认证的安全参数,能够有效地保护安全参数不被窃取。认证方案在认证过程中对用户的身份信息进行了保护,使用Hash运算计算认证参数,通过用户端和服务器端之间的认证参数的...
在身份认证技术中,EKE协议(Encrypted Key Exchange Protocol)是一种重要的密钥交换协议,它特别适用于弱口令条件下的安全通信。EKE协议的基础是Diffie-Hellman密钥交换协议的加密版本,可以有效地抵抗离线字典...
电子商务安全方案设计是确保在线交易和信息交换安全的关键环节。这一方案涉及到多种技术和协议,旨在保护用户身份、数据完整性和通信隐私。以下是对这些知识点的详细解释: 1. **身份认证**: - **单向函数口令...
该程序主要通过以下几个步骤来实现口令验证的功能: - **第一步:** 用户首先需要输入预设的口令。 - **第二步:** 程序检查是否存在一个名为`password.dat`的文件。如果文件存在,则从中读取存储的口令;如果文件...
在本Java源代码中,我们可以推测其设计了一个算法,该算法能够生成这些动态口令。这种算法可能基于时间同步(Time-based One-Time Password, TOTP)或事件同步(Event-based One-Time Password, OTP),前者基于当前...
总结起来,这个“公司部门内部留言本”是一款基于Struts和JSP开发的内部通讯工具,具备留言、文件上传下载及口令验证等功能,旨在提升团队沟通效率,保障信息安全。它的设计和实现利用了成熟的Java Web技术,确保了...
同时,需要考虑到在没有网络连接或者设备丢失的情况下的备用验证方案。 7. **安全性考虑**:除了动态口令外,系统还应包含其他安全措施,如会话管理、XSS和CSRF防护,以及对SQL注入的防范,以提高整体安全性。 8. ...
### Web网站统一口令认证系统的设计与实现 #### 摘要分析 当前Web网站认证系统存在的主要问题包括用户认证的繁琐性和后续认证方法的安全隐患。由于不同网站或同一网站内的不同服务各自独立管理和维护各自的认证系统...
本文提出了一种安全的动态口令鉴别(认证)方案(SDPA),该方案旨在解决在不安全网络通道上进行用户身份验证的问题。与传统的静态密码认证方法相比,SDPA通过引入额外的小量计算负担来显著提升安全性。传统方法如...
【摘要】介绍了一种结合数字签名和动态口令的双向动态身份认证方案,旨在提高网络安全性和用户身份验证的可靠性。方案基于公钥密码机制实现数字签名的原理,结合挑战应答机制,确保了消息的完整性和真实性,同时能...
- **密钥管理**: 需要设计一套安全的密钥管理系统来管理和保护摘要口令和加密密钥,以防止它们被未经授权的访问或使用。 #### 实现优势 - **提高安全性**: 通过将私钥加密并与摘要口令相结合,大大降低了私钥被...
2. **口令验证**:当用户输入动态口令时,服务器需要验证其有效性。这包括计算当前时间戳对应的预期口令并与用户输入的口令进行比较。如果匹配,则验证成功,否则拒绝登录。 3. **时间同步**:动态口令的有效期通常...
### RFC4226 - otpc - 动态口令系统 #### 概述 《RFC4226》标准定义了一种名为HOTP(HMAC-based ...这种机制在现代身份验证方案中被广泛采用,特别是在多因素认证中,为用户提供了一个既安全又便捷的身份验证方式。