Java的MD5工具类和客户端测试类

作者:不再简简单单 时间:2022-04-23 03:08:48 

什么是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

标签:Java,MD5
0
投稿

猜你喜欢

  • springboot 正确的在异步线程中使用request的示例代码

    2023-11-24 22:36:13
  • Java中IO流文件读取、写入和复制的实例

    2023-08-12 03:23:29
  • Android studio删除Android项目方法

    2022-01-24 01:56:05
  • Android Activity生命周期调用的理解

    2023-05-13 14:15:42
  • C#实现的文件压缩和解压缩类

    2022-11-30 16:08:08
  • c#实现图片二值化例子(黑白效果)

    2023-02-19 11:52:46
  • java高并发写入用户信息到数据库的几种方法

    2023-07-09 08:45:49
  • Java控制台输入数组并逆序输出的方法实例 <font color=red>原创</font>

    2023-07-13 23:32:26
  • Redis使用RedisTemplate模板类的常用操作方式

    2023-01-30 08:33:40
  • C#中实现AES算法加密解读

    2022-09-17 16:49:36
  • Android如何使用RecyclerView打造首页轮播图

    2022-06-08 13:15:39
  • c#线程同步使用详解示例

    2021-06-15 19:22:58
  • 深入解析java中的locale

    2023-11-09 18:14:20
  • C#实现最完整的文件和目录操作类实例

    2022-05-19 09:38:51
  • 分享Java多线程实现的四种方式

    2022-02-23 06:34:21
  • Android集成微信支付功能

    2023-07-14 10:38:11
  • JAVA集合框架Map特性及实例解析

    2021-06-05 02:23:39
  • 初步了解javafx

    2021-09-30 16:20:11
  • Spring boot jpa 删除数据和事务管理的问题实例详解

    2022-07-02 12:11:43
  • Android仿微信语音聊天界面设计

    2023-01-10 01:33:28
  • asp之家 软件编程 m.aspxhome.com