Java的MD5工具类和客户端测试类
作者:不再简简单单 发布时间:2022-04-23 03:08:48
标签:Java,MD5
什么是MD5?
Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。该算法的文件号为RFC 1321(R.Rivest,MIT Laboratory for Computer Science and RSA Data Security Inc. April 1992)。
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。
MD5算法具有以下特点:
1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。
2、容易计算:从原数据计算出MD5值很容易。
3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
4、强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
一个工具类
package com.huaidan.utils;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
public class MyMD5Util {
private static final String HEX_NUMS_STR="0123456789ABCDEF";
private static final Integer SALT_LENGTH = 12;
/**
* 将16进制字符串转换成字节数组
* @param hex
* @return
*/
public static byte[] hexStringToByte(String hex) {
int len = (hex.length() / 2);
byte[] result = new byte[len];
char[] hexChars = hex.toCharArray();
for (int i = 0; i < len; i++) {
int pos = i * 2;
result[i] = (byte) (HEX_NUMS_STR.indexOf(hexChars[pos]) << 4
| HEX_NUMS_STR.indexOf(hexChars[pos + 1]));
}
return result;
}
/**
* 将指定byte数组转换成16进制字符串
* @param b
* @return
*/
public static String byteToHexString(byte[] b) {
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
hexString.append(hex.toUpperCase());
}
return hexString.toString();
}
/**
* 验证口令是否合法
* @param password
* @param passwordInDb
* @return
* @throws NoSuchAlgorithmException
* @throws UnsupportedEncodingException
*/
public static boolean validPassword(String password, String passwordInDb)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
//将16进制字符串格式口令转换成字节数组
byte[] pwdInDb = hexStringToByte(passwordInDb);
//声明盐变量
byte[] salt = new byte[SALT_LENGTH];
//将盐从数据库中保存的口令字节数组中提取出来
System.arraycopy(pwdInDb, 0, salt, 0, SALT_LENGTH);
//创建消息摘要对象
MessageDigest md = MessageDigest.getInstance("MD5");
//将盐数据传入消息摘要对象
md.update(salt);
//将口令的数据传给消息摘要对象
md.update(password.getBytes("UTF-8"));
//生成输入口令的消息摘要
byte[] digest = md.digest();
//声明一个保存数据库中口令消息摘要的变量
byte[] digestInDb = new byte[pwdInDb.length - SALT_LENGTH];
//取得数据库中口令的消息摘要
System.arraycopy(pwdInDb, SALT_LENGTH, digestInDb, 0, digestInDb.length);
//比较根据输入口令生成的消息摘要和数据库中消息摘要是否相同
if (Arrays.equals(digest, digestInDb)) {
//口令正确返回口令匹配消息
return true;
} else {
//口令不正确返回口令不匹配消息
return false;
}
}
/**
* 获得加密后的16进制形式口令
* @param password
* @return
* @throws NoSuchAlgorithmException
* @throws UnsupportedEncodingException
*/
public static String getEncryptedPwd(String password)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
//声明加密后的口令数组变量
byte[] pwd = null;
//随机数生成器
SecureRandom random = new SecureRandom();
//声明盐数组变量
byte[] salt = new byte[SALT_LENGTH];
//将随机数放入盐变量中
random.nextBytes(salt);
//声明消息摘要对象
MessageDigest md = null;
//创建消息摘要
md = MessageDigest.getInstance("MD5");
//将盐数据传入消息摘要对象
md.update(salt);
//将口令的数据传给消息摘要对象
md.update(password.getBytes("UTF-8"));
//获得消息摘要的字节数组
byte[] digest = md.digest();
//因为要在口令的字节数组中存放盐,所以加上盐的字节长度
pwd = new byte[digest.length + SALT_LENGTH];
//将盐的字节拷贝到生成的加密口令字节数组的前12个字节,以便在验证口令时取出盐
System.arraycopy(salt, 0, pwd, 0, SALT_LENGTH);
//将消息摘要拷贝到加密口令字节数组从第13个字节开始的字节
System.arraycopy(digest, 0, pwd, SALT_LENGTH, digest.length);
//将字节数组格式加密后的口令转化为16进制字符串格式的口令
return byteToHexString(pwd);
}
}
测试类客户端
package com.huaidan.test;
import com.huaidan.utils.MyMD5Util;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
public class Client {
private static Map users = new HashMap();
public static void main(String[] args){
String userName = "zyg";
String password = "123";
registerUser(userName,password);
userName = "changong";
password = "456";
registerUser(userName,password);
String loginUserId = "zyg";
String pwd = "123";
try {
if(loginValid(loginUserId,pwd)){
System.out.println("欢迎登陆!!!");
}else{
System.out.println("口令错误,请重新输入!!!");
}
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 注册用户
*
* @param userName
* @param password
*/
public static void registerUser(String userName,String password){
String encryptedPwd = null;
try {
encryptedPwd = MyMD5Util.getEncryptedPwd(password);
System.out.println("加密后的用户密码"+encryptedPwd);
users.put(userName, encryptedPwd);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 验证登陆
*
* @param userName
* @param password
* @return
* @throws UnsupportedEncodingException
* @throws NoSuchAlgorithmException
*/
public static boolean loginValid(String userName,String password)
throws NoSuchAlgorithmException, UnsupportedEncodingException{
String pwdInDb = (String)users.get(userName);
System.out.println(pwdInDb);
if(null!=pwdInDb){ // 该用户存在
return MyMD5Util.validPassword(password, pwdInDb);
}else{
System.out.println("不存在该用户!!!");
return false;
}
}
}
来源:https://blog.csdn.net/simple_start/article/details/91405255


猜你喜欢
- 先看看效果图:中间的圆形头像和光环波形讲解请看:https://www.jb51.net/article/96508.htm周围的气泡布局,
- What内含一个或多个maven模块的SpringBoot项目称为SpringBoot多模块项目Why便于维护 将一个大的单体项目分成多个子
- 本文实例为大家分享了spring aop注解配置的具体代码,供大家参考,具体内容如下Demo.javapackage cn.itcast.e
- 1、synchronized 方法与锁对象线程锁的是对象。1)A线程先持有 object 对象的 Lock 锁, B线程可以以异步的方式调用
- 本文实例为大家分享了Android Studio实现简易计算器App的具体代码,供大家参考,具体内容如下效果演示布局文件<?xml v
- 本文实例讲述了C#通过WIN32 API实现嵌入程序窗体的方法,分享给大家供大家参考。具体如下:这是一个不使用COM,而是通过WIN32 A
- Web Fragment 是什么 - 它是在 servlet 3.0开始支持的,可以把一个dy web项目拆分为多个项目,解耦合,使其在项目
- 被接受的特性1. Jigsaw 项目;模块化源码Jigsaw项目是为了模块化Java代码、将JRE分成可相互协作的组件,这也是Java 9
- 布局:<?xml version="1.0" encoding="utf-8"?><
- 本文实例讲述了Android实现EditText中添加和删除bitmap的方法。分享给大家供大家参考,具体如下:SpannableStrin
- 一、前言在C#中,由于有了垃圾回收机制的支持,对象的析构和以前的C++有了很大的不同,这就要求程序员在设计类型的时候,充分理解.NET的机制
- 接口直接返回图片数据起因最近在做涉及到分享推广的业务,需要由业务员分享二维码进入推广页面,由于是新项目,前期预算和用量都有限,没有搭建对象存
- 创建SpringBoot项目,启动后,默认的访问路径即主机IP+默认端口号8080:http://localhost:8080/此时,我们就
- 1 在图片上用鼠标进行操作,opencv主要用到setMouseCallback()函数。winname 窗口名称onMouse 鼠标事件的
- 关于Android的webview,用过的想必都不会陌生。这里我就不说webview的基本用法了,想要知道的可以去网上百多,有很多介绍web
- 之前在博文中为了更好的给大家演示APP的实现效果,本人了解学习了几种给手机录屏的方法,今天就给大家介绍两种我个人用的比较舒服的两种方法:(1
- 1.新建文件上传页面在static目录中新建upload-test.html,上传页面代码如下所示:<!DOCTYPE html>
- java 算法之归并排序详解一、思想 归并排序:将一个数组排序,可以先(递归地)将它分成两半部份分别排序,然后将结果归并起来; &
- 前言Object object = new Object();世间万物的本质都可看作类的对象,面向对象(OOP)的模式让程序易维护、易复用、
- 前言如何下载和使用MyBatis Generator 插件,只说代码,不讲感情。如果有问题还请多多指点。开发环境开发工具:IntelliJ