【项目小知识】Java中的Md5加密——Md5Util类

我是灼灼,一只初学Java的大一金渐层。
向往余秀华和狄兰·托马斯的疯狂,时常沉溺于将情感以诗相寄;追逐过王尔德、王小波的文字,后陷于毛姆和斯蒂芬·金不可自拔;热爱文学的浪潮,白日梦到底却总在现实里清醒;艳羡平静又极度渴盼奔跑的力量。
欢迎与我交流鸭· QQ:1517526827;
个人博客:https://blog.csdn.net/weixin_52777510?spm=1001.2101.3001.5343

对数据库中用户的密码实现Md5加密

Md5加密是利用哈希算法实现的
其实我也看不懂写的是什么…

参考博客一
参考博客二
参考博客三

Java实现MD5加密的方式

MD5加密是一种常见的加密方式,经常用在保存用户密码和关键信息上。

1、什么是MD5
  MD5加密全称是Message-Digest Algoorithm 5(信息-摘要算法),它对信息进行摘要采集,再通过一定的位运算,最终获取加密后的MD5字符串。
  例如要加密一篇文章,会随机从每段话或者每行中获取一个字,把这些字统计出来后,再通过一定的运算获得一个固定长度的MD5加密后信息。因此,其很难被逆向破解
  
MD5加密流程图!
  在这里插入图片描述
2、MD5有哪些特点
 MD5加密的特点主要有以下几点:

  • 针对不同长度待加密的数据、字符串等等,其都可以返回一个固定长度的MD5加密字符串。(通常32位的16进制字符串);
  • 其加密过程几乎不可逆,除非维护一个庞大的Key-Value数据库来进行碰撞破解,否则几乎无法解开
  • 运算简便,且可实现方式多样,通过一定的处理方式也可以避免碰撞算法的破解。
  • 对于一个固定的字符串。数字等等,MD5加密后的字符串是固定的,也就是说不管MD5加密多少次,都是同样的结果

3、Java中MD5加密的实现方式

public static String getMD5String(String str) {
    
    
        try {
    
    
            // 生成一个MD5加密计算摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 计算md5函数
            md.update(str.getBytes());
            // digest()最后确定返回md5 hash值,返回值为**8位字符串**。因为md5 hash值是**16位的hex值**,实际上就是**8位的字符**
            // BigInteger函数则**将8位的字符串转换成16位hex值**,用**字符串**来表示;**得到字符串形式的hash值**
            //一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方)
            return new BigInteger(1, md.digest()).toString(16);
        } catch (Exception e) {
    
    
           e.printStackTrace();
           return null;
        }
    }

上述的是利用Java自带的MessageDigest类实现的最简单的MD5加密方法。对加密过程没有做任何处理。下面这个相对来说更加复杂。

package com.mmall.util;
import java.security.MessageDigest;
/**
 * Created by dt
 */
public class MD5Util {
    
    

  //这里主要是遍历8个byte,转化为16位进制的字符,即0-F
    private static String byteArrayToHexString(byte b[]) {
    
    
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++)
            resultSb.append(byteToHexString(b[i]));
        return resultSb.toString();
    }
  //这里是针对单个byte,256的byte通过16拆分为d1和d2
    private static String byteToHexString(byte b) {
    
    
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }
    /**
     * 返回大写MD5
     *
     * @param origin
     * @param charsetname
     * @return
     */
   private static String MD5Encode(String origin, String charsetname) {
    
    
        String resultString = null;
        try {
    
    
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname))
                resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
            else
                resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
        } catch (Exception exception) {
    
    
        }
        return resultString.toUpperCase();
    }

    public static String MD5EncodeUtf8(String origin) {
    
    
        origin = origin + PropertiesUtil.getProperty("password.salt","");
        return MD5Encode(origin, "utf-8");
    }


    private static final String hexDigits[] = {
    
    "0", "1", "2", "3", "4", "5","6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

}

还有个更详细的版本,附有更详细的注释:

public static String stringMD5(String input) {
    
    
  try {
    
    
  
     // 拿到一个MD5转换器(如果想要SHA1参数换成”SHA1”)
     MessageDigest messageDigest =MessageDigest.getInstance("MD5");

     // 输入的字符串转换成字节数组
     byte[] inputByteArray = input.getBytes();

     // inputByteArray是输入字符串转换得到的字节数组
     messageDigest.update(inputByteArray);

     // 转换并返回结果,也是字节数组,包含16个元素
     byte[] resultByteArray = messageDigest.digest();

     // 字符数组转换成字符串返回
     return byteArrayToHex(resultByteArray);

  } catch (NoSuchAlgorithmException e) {
    
    
     return null;
  }
}

//下面这个函数用于将字节数组换成成16进制的字符串
public static String byteArrayToHex(byte[] byteArray) {
    
    

  // 首先初始化一个字符数组,用来存放每个16进制字符
  char[] hexDigits = {
    
    '0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F' };

  // new一个字符数组,这个就是用来组成结果字符串的(解释一下:一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方))
  char[] resultCharArray =new char[byteArray.length * 2];

  // 遍历字节数组,通过位运算(位运算效率高),转换成字符放到字符数组中去
  int index = 0;
  for (byte b : byteArray) {
    
    
     resultCharArray[index++] = hexDigits[b>>> 4 & 0xf];
     resultCharArray[index++] = hexDigits[b& 0xf];
  }

  // 字符数组组合成字符串返回
  return new String(resultCharArray);
}

java将字符串进行MD5加密

/**
	 * Encodes a string 2 MD5
	 * 
	 * @param str String to encode
	 * @return Encoded String
	 * @throws NoSuchAlgorithmException
	 */
public class MD5Util {
    
    
	public static String crypt(String str) {
    
    
		if (str == null || str.length() == 0) {
    
    
			throw new IllegalArgumentException("String to encript cannot be null or zero length");
		}
		StringBuffer hexString = new StringBuffer();
		try {
    
    
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(str.getBytes());
			byte[] hash = md.digest();
			for (int i = 0; i < hash.length; i++) {
    
    
				if ((0xff & hash[i]) < 0x10) {
    
    
					hexString.append("0" + Integer.toHexString((0xFF & hash[i])));
				} else {
    
    
					hexString.append(Integer.toHexString(0xFF & hash[i]));
				}
			}
		} catch (NoSuchAlgorithmException e) {
    
    
			e.printStackTrace();
		}
		return hexString.toString();
	}
}

学长的Md5加密实现代码:

public class Md5Util {
    
    
        public static String stringToMD5(String plainText) {
    
    
            byte[] secretBytes = null;
            try {
    
    
                secretBytes = MessageDigest.getInstance("md5").digest(
                        plainText.getBytes());
            } catch (NoSuchAlgorithmException e) {
    
    
                throw new RuntimeException("md5算法不存在");
            }
            String md5code = new BigInteger(1, secretBytes).toString(16);
            for (int i = 0; i < 32 - md5code.length(); i++) {
    
    
                md5code = "0" + md5code;
            }
            return md5code;
        }
}

Java实现MD5加密及解密的代码实例分享(大佬的代码仅作观赏之用…)

如果对安全性的需求不是太高,MD5仍是使用非常方便和普及的加密方式,比如Java中自带的MessageDigest类就提供了支持,这里就为大家带来Java实现MD5加密及解密的代码实例分享:

基础:MessageDigest类的使用

其实要在Java中完成MD5加密,MessageDigest类大部分都帮你实现好了,几行代码足矣:

/**
 * 对字符串md5加密
 *
 * @param str
 * @return
 */
import java.security.MessageDigest;
public static String getMD5(String str) {
    
    
 try {
    
    
 // 生成一个MD5加密计算摘要
 MessageDigest md = MessageDigest.getInstance("MD5");
 // 计算md5函数
 md.update(str.getBytes());
 // digest()最后确定返回md5 hash值,返回值为8为字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符
 // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值
 return new BigInteger(1, md.digest()).toString(16);
 } catch (Exception e) {
    
    
 throw new SpeedException("MD5加密出现错误");
 }
}

进阶:加密及解密类
Java实现MD5加密以及解密类,附带测试类,具体见代码。

MD5加密解密类——MyMD5Util,代码如下:

package com.zyg.security.md5;

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);
 }
}

测试类——Client,代码如下:

package com.zyg.security.md5;

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 = "1232";
 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);
 
 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);
 if(null!=pwdInDb){
    
     // 该用户存在
 return MyMD5Util.validPassword(password, pwdInDb);
 }else{
    
    
 System.out.println("不存在该用户!!!");
 return false;
 }
 }
}

分享到此结束啦~
作为项目小白的我只需要学会Java自带的最简单的加密方式就可以啦!
大家一起加油!

在这里插入图片描述
如果对你有帮助的话不要忘记一键三连噢~
谢谢鸭~

初次编写于2021/2/18日;

猜你喜欢

转载自blog.csdn.net/weixin_52777510/article/details/113854516