开发者社区> 问答> 正文

MD5是什么?

MD5应该怎么用?

展开
收起
问问小秘 2020-04-30 16:33:43 7209 0
2 条回答
写回答
取消 提交回答
  • 有点尴尬唉 你要寻找的东西已经被吃掉啦!

    一.作用:一般用于互联网一种数据的唯一性标识。

    二.实体:本身是一个128位的0/1比特。一般被表示为16进制的字符串。4个比特位组成一个16进制字符,因此常常能见到的是(128/4=)32个16进制字符组成的字符串 4951 dd1c bff8 cbbe 4cd4 475c a939 fc8b,当然它实质是一种消息摘要算法

    三.特点:

    1.完全相同的一段数据,不论时间地点(加密算法相同的条件)加密出的32位的字符串完全相同。

    2.加密过程本身就是一个有损的加密过程。因此几乎不能还原出原始数据。安全

    补充:一般还原出原始数据都是使用碰撞的方式来还原。意思大概和穷举的意思一样,有足够多的原始数据量,世界上的所有数据用 1~n来表示,把1~n都用MD5计算一遍得1x~nx(x表示计算后得的数)。把1~n当成键值对的键,把1x~nx放入键值对的值,当得到一个MD5字符串,通过值去找键,就知道是什么数据了。因为你本来就拥有数据,因此才能找到数据。但当你没有原始数据时,想通过128比特的玩意去恢复大于128比特的数据本身就是玩笑,数据量都不一样,至于原理有兴趣的朋友可以研究研究信息论。不想研究的可以回想回想之前学的香农公式。再从这一点去研究。又有大的世界。
    

    3.散列能力巨强。安全

    2020-04-30 18:07:08
    赞同 展开评论 打赏
  • 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值的数据(即伪造数据)是非常困难的。

    一个工具类

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

    测试类客户端

    
    
    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;
    
            }
    
        }
    
    }
    
    2020-04-30 16:35:36
    赞同 展开评论 打赏
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载