package com.cinc.ecmp.userpermission.utils;

import java.security.MessageDigest;
import java.security.SecureRandom;

/**
 * @Author: hhr
 * @Despriction: md5加解密密码
 * @CreatedTime: 2019/6/13 10:02
 * @ModifyBy:
 * @ModifyTime:
 * @ModifyDespriction:
 * @Version: V1.0.0
 */
public class MD5Utils {
    /**
     *  盐值长度
     */
    private static final int SALT_LENGTH = 30;
    /**
     *  加密算法
     */
    private static final String ALGORITHM = "MD5";
    /**
     *  编码
     */
    private static final String CHARSET = "UTF-8";
    /**
     *  密码加密长度
     */
    private static final int MD5_LENGTH = 32;

/**
     * byte数组转换成十六进制字符串
     *
     * @param bytes byte数组
     * @return
     */
    private static String bytesToHexStr(byte[] bytes) {
        String tmp = "";
        StringBuilder sb = new StringBuilder("");
        for (int i = 0; i < bytes.length; i++) {
            tmp = Integer.toHexString(bytes[i] & 0xFF);
            sb.append((tmp.length() == 1) ? "0" + tmp : tmp);
        }
        return sb.toString().toUpperCase().trim();
    }

/**
     * 十六进制字符串转成byte数组
     * @param hexStr 十六进制字符串
     * @return
     */
    private static byte[] hexStrToBytes(String hexStr) {
        byte[] bytes = new byte[hexStr.length() / 2];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) Integer.parseInt(hexStr.substring(2 * i, 2 * i + 2), 16);
        }
        return bytes;
    }

/**
     * 生成随机盐
     * @return 返回长度为SALT_LENGTH * 2的盐
     */
    public static String createSaltValue() {
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[SALT_LENGTH];
        random.nextBytes(salt);
        return bytesToHexStr(salt);
    }

/**
     * 用户密码使用md5加密
     * @param password  用户密码
     *@return 返回长度为32位的16进制字符串
     */
    public static String md5EncodePwd(String password) {
        try {
            MessageDigest digest = MessageDigest.getInstance(ALGORITHM);
            byte[] result = digest.digest(password.getBytes(CHARSET));
            return bytesToHexStr(result);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

/**
     * 按照salt+pwd的顺序返回最终要保存到数据库的密码
     * @param salt  随机盐
     * @param md5encodePwd  经过md5加密的字符串
     *@return   按照规则返回的最终密码
     */
    public static String getFinalPwd(String salt, String md5encodePwd) {
        StringBuilder stringBuilder = new StringBuilder();
        /**
         * 前64位规则:
         *      奇数位是用户真实密码的hash值
         *      偶数为是盐值
         * 后16位:是剩余的盐值
         */
        for (int i = 0; i < md5encodePwd.length(); i++) {
            stringBuilder.append(md5encodePwd.substring(i, i + 1)).append(salt.substring(i, i + 1));
        }
        stringBuilder.append(salt.substring(md5encodePwd.length(), salt.length()));
        return stringBuilder.toString();
    }

/**
     * 按照salt+pwd的顺序返回最终要保存到数据库的密码
     * @return    按照规则返回的最终密码
     */
    public static String createHashPwd(String password) {
        return getFinalPwd(createSaltValue(), md5EncodePwd(password));
    }

/**
     * 从数据库中保存的最终密码,解析出用户真实秘密的md5加密串
     * @return  返回真实秘密的加密串
     */
    public static String getUserPwdMD5(String finalPwd) {
        try {
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < MD5_LENGTH * 2; i += 2) {
                stringBuilder.append(finalPwd.substring(i, i + 1));
            }
            return stringBuilder.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

/**
     * 验证用户输入的密码是否正确
     * @param password  用户输入的密码
     * @param finalPwd  数据库中保存的密码
     * @return
     * 验证结果:true密码正确,反之密码错误
     */
    public static boolean verifyPwd(String password, String finalPwd) {
        return password == null ? false : md5EncodePwd(password).equals(getUserPwdMD5(finalPwd));
    }

public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("");
        for (int i = 0; i < 100; i++) {
            /* 生成加密密码 */
            String userPwd = "yan123shao@wy" + i;
            String salt = createSaltValue();
            System.out.println("盐值>>" + salt);
            String md5encodePwd = md5EncodePwd(userPwd);
            System.out.println("md5>>" + md5encodePwd);
            String finalPwd = getFinalPwd(salt, md5encodePwd);
            if (sb.toString().contains(finalPwd)) {
                System.out.println("重复的密码>>" + finalPwd);
                break;
            }
            sb.append(finalPwd);
            System.out.println("最终密码>>" + finalPwd);
            /**用户登录输入密码,验证秘密是否正确*/
            boolean verify = verifyPwd(userPwd, finalPwd);
            System.out.println("密码正确");
            if (verify == false) {
                System.out.println("输入的密码>>" + userPwd + ">>密码验证失败>>" + getUserPwdMD5(finalPwd));
                break;
            }
        }
    }

}

MD5登陆密码的生成的更多相关文章

  1. 忘记hmailiserver邮件服务器后台登陆密码解决

    进入后台进行hmailiserver的相关设置,发现登陆密码忘记了,如下图:

  2. Android MD5校验码的生成与算法实现

    在Java中,java.security.MessageDigest (rt.jar中)已经定义了 MD5 的计算,所以我们只需要简单地调用即可得到 MD5 的128 位整数.然后将此 128 位计 ...

  3. 类似discuz密码的生成规则

    /* 生成一个串,uniqid(rand()): uniqid(prefix,more_entropy) 函数基于以微秒计的当前时间,生成一个唯一的 ID. 如果 prefix 参数为空,则返回的字符 ...

  4. 忘记Windows7登陆密码解决办法

    忘记 Windows7 的登陆密码,解决这个问题的思路就是替换 system32 下的 Magnify.exe . 可以从 WindowsPE 启动,到 C:\windows\system32 下. ...

  5. Win7开机登陆密码忘记了?不必重做系统(详图)

     1)如果是普通账户密码忘了.方法:重新启动电脑,启动到系统登录界面时,同时按住Ctrl+Alt键,然后连击Del键两次,会出现新的登录界面,用户名处输入“Administrator”密码为空,回车即 ...

  6. linux普通用户权限设置为超级用户权限方法、sudo不用登陆密码

    以用户zato为例 普通用户权限设置为超级用户权限 进入有超级用户权限的账号 添加文件可写(w)权限 sudo chmod u+x /etc/sudoers 编辑/etc/sudoers文件 添加语句 ...

  7. WebCracker4.0和monster字典——路由器登陆密码破解工具

    路由器登陆密码破解,很伤cpu的

  8. Win10 登陆密码不正确(安全模式仍然启动不了)

    今天朋友重启Win10后,登陆密码显示不正确,是用了很多方法都不行 然后就瞎捣鼓就进去 进入BIOS将启动模式调为USB模式 重启启动不了后 再改回系统启动 就进去了(好神奇)

  9. thinkcmf 忘记后台登陆密码的解决办法

    thinkcmf 忘记密码 或者 密码错误 如何修改后台登陆密码? 直接在后台登陆控制器里输入 dump(cmf_password('123456')); 参考文件路径 app\admin\contr ...

随机推荐

  1. day3-转自金角大王

    本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...

  2. 总结 ESP8266 RTOS 开发环境搭建

    总结 ESP8266 RTOS 开发环境搭建 仔细看官方文档. 必须一步一步操作. 不要想当然,以为 make 就可以. 忽略编译警告,除非是错误. 工具链必须使用官方提供的. 多看看 Issues ...

  3. BZOJ3832Rally题解

    一道思维神题.... 我们像网络流一样加入原点S,与汇点T 用f[i]表示原点到i的最长路,用g[i]表示i到汇点的最长路 f数组与g数组都可以dp求出来的 接下来考虑如何通过这些信息来维护删除某个点 ...

  4. QPS 提升60%,揭秘阿里巴巴轻量级开源 Web 服务器 Tengine 负载均衡算法

    前言 在阿里七层流量入口接入层(Application Gateway)场景下, Nginx 官方的Smooth Weighted Round-Robin( SWRR )负载均衡算法已经无法再完美施展 ...

  5. 【JZOJ4847】【NOIP2016提高A组集训第5场11.2】夕阳

    题目描述 "我有个愿望,我希望在灿烂千阳时遇见你." 这是个有n个点的世界,有m条无向边连接着这n个点,但是不保证点之间能够互相到达. "这个世界的夕阳,只在奇数长的简单 ...

  6. 【Django入坑之路】Django与Query Ajax的交互

    1:Jquery.ajax后端交互数据 $.ajax({ Url: /路由处理/, Type: GET/POST, #传送请求类型 Data: {user: “ XXXX”,pass:”XXXX”}, ...

  7. 2018-8-9-win10-uwp-装机必备应用-含源代码

    title author date CreateTime categories win10 uwp 装机必备应用 含源代码 lindexi 2018-8-9 9:7:31 +0800 2018-8-9 ...

  8. Android中解析Json数据

    在开发中常常会遇到解析json的问题 在这里总结几种解析的方式: 方式一: json数据: private String jsonData = "[{\"name\":\ ...

  9. 谷歌BERT预训练源码解析(二):模型构建

    目录前言源码解析模型配置参数BertModelword embeddingembedding_postprocessorTransformerself_attention模型应用前言BERT的模型主要 ...

  10. JVM -XX: 参数列表

    功能开关: 参数 默认值或限制 说明 参数 默认值 功能 -XX:-AllowUserSignalHandlers 限于Linux和Solaris,默认不启用 允许为java进程安装信号处理器,信号处 ...