package cn.ey.biz.module.external.utils;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.digest.MD5;

import java.math.BigInteger;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;

public class MD5Utils {
    /**
     * 随机盐值字节数
     */
    private static final int SALT_BYTE_LENGTH = 20;
    private static final Charset CHARSET = StandardCharsets.UTF_8;
	public static String encrypt(String str){
        //定义一个字节数组
        byte[] secretBytes = null;
        try {
            // 生成一个MD5加密计算摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            //对字符串进行加密
            md.update(str.getBytes());
            //获得加密后的数据
            secretBytes = md.digest();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("没有md5这个算法！");
            //throw new RuntimeException(SystemEnv.getHtmlLabelName(517545,userLanguage));
        }
        //将加密后的数据转换为16进制数字
        String md5code = new BigInteger(1, secretBytes).toString(16);
        // 如果生成数字未满32位，需要前面补0
        // 不能把变量放到循环条件，值改变之后会导致条件变化。如果生成30位 只能生成31位md5
        int tempIndex = 32 - md5code.length();
        for (int i = 0; i < tempIndex; i++) {
            md5code = "0" + md5code;
        }
        return md5code;
        }

    public static String encryptSalt(String password){
        SecureRandom secureRandom = new SecureRandom();
        byte[] salt = new byte[SALT_BYTE_LENGTH];
        secureRandom.nextBytes(salt);
        MD5 md5 = new MD5(salt);
        byte[] digest = md5.digest(password,CHARSET);
        //填充前20个字节为盐值，校验密码时候需要取出
        byte[] pwd = ArrayUtil.addAll(salt,digest);
        return HexUtil.encodeHexStr(pwd);
    }

    public static boolean valid(String password,String encryptedPassword){
        byte[] encryptedPwd = HexUtil.decodeHex(encryptedPassword);
        //取出前20个字节盐值
        byte[] salt =  ArrayUtil.sub(encryptedPwd,0,SALT_BYTE_LENGTH);
        //20字节后为真正MD5后密码
        byte[] pwd = ArrayUtil.sub(encryptedPwd,SALT_BYTE_LENGTH,encryptedPwd.length);
        MD5 md5 = new MD5(salt);
        byte[] digest = md5.digest(password,CHARSET);
        return Arrays.equals(digest,pwd);
    }


	public static void main(String[] args) {
		
		System.out.println(MD5Utils.encrypt("admin"));
        System.out.println(MD5Utils.encryptSalt("admin"));
        System.out.println(MD5Utils.valid("admin","ff66b24e0017b32400951280a4a3c2672afa266dd92fab8a87cb11f2401a8f97e301db69"));
	}

}
