zoukankan      html  css  js  c++  java
  • MD5盐值加密

    加密思路

    QQ图片20170315133952

    思路解析:(数据解析过程基于16进制来处理的,加密后为16进制字符串)

    加密阶段:

    对一个字符串进行MD5加密,我们需要使用到MessageDigest(消息摘要对象),需要一个盐值(salt),这个值可以是我们在业务中的一个标识号,比如银行业务中的商户号。

    然后对使用salt对password进行组合加密,形成一个加密串Encryp_password,但这时候并不是真正完整的加密串,我们还需要将salt放到加密串的最前面,方便在数据验证时,获取salt

    因此最终的加密串为:SAL_Encryp_password=salt+Encryp_password.

    解密验证阶段(实际上就是源字符串的再加密):

    我们需要根据加密后的加密串获取到salt,然后使用salt对源字符串进行加密,得到新的加密串Encryp_password,然后两者相比,如果比对上,验证成功,否则验证失败!

    加密类

    package com.alivn.utils;
    import java.io.UnsupportedEncodingException;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.util.Arrays;
    
    /**
     * Created by Stringbuilder_Sun on 2017/3/15.
     */
    public class MD5Encoder {
    
        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];
            //将盐从<a href="http://lib.csdn.net/base/mysql" class='replace_word' title="MySQL知识库" target='_blank' style='color:#df3434; font-weight:bold;'>数据库</a>中保存的口令字节数组中提取出来
            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.alivn.utils;
    
    import java.io.UnsupportedEncodingException;
    import java.security.NoSuchAlgorithmException;
    import java.util.HashMap;
    import java.util.Map;
    
    
    public class  TestMD5Ecoder{
        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 = MD5Encoder.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 MD5Encoder.validPassword(password, pwdInDb);
            }else{
                System.out.println("不存在该用户!!!");
                return false;
            }
        }
    }

     

  • 相关阅读:
    《Unix/Linux系统编程》第九章学习笔记
    第1、2章学习笔记
    第11章学习笔记(20191213兰毅达)
    第7、8章学习笔记(20191213兰毅达)
    sort(20191213兰毅达)
    # 电子公文传输系统团队项目 团队作业(一):团队展示
    第10章学习笔记(20191213兰毅达)
    MyOD(选做)(20191213兰毅达)
    2019-2020-1 20191213兰毅达《信息安全专业导论》第十二周学习总结
    2019-2020-1 20191213兰毅达《信息安全专业导论》第十一周学习总结
  • 原文地址:https://www.cnblogs.com/ljp-sun/p/6553910.html
Copyright © 2011-2022 走看看