Java实现MD5加密的四种方式

2025-03-18 14:50

本文主要是介绍Java实现MD5加密的四种方式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Java实现MD5加密的四种方式》MD5是一种广泛使用的哈希算法,其输出结果是一个128位的二进制数,通常以32位十六进制数的形式表示,MD5的底层实现涉及多个复杂的步骤和算法,本文给大家介绍了Ja...

MD5介绍

MD5(Message-Digest Algorithm 5)是一种广泛使用的哈希算法,其输出结果是一个128位的二进制数,通常以32位十六进制数的形式表示。因此,MD5的输出结果可以表示为一个32位的字符串。

MD5算法常用于数据完整性验证、密码加密等场景,通常将输入的数据经过MD5处理后,得到一个32位的摘要(digest),该摘要作为数据的唯一表示,可以用于验证数据的完整性或作为密码的加密存储。需要注意的是,由于MD5算法本身存在安全性问题,已经不再推荐用于密码加密等安全场景,而应该使用更加安全的算法,如SHA-2、bcrypt等。

MD5(Message Digest Algorithm 5)是一种哈希函数,而不是对称加密算法。MD5 用于产生一个称为消息摘要(Message Digest)的固定大小的哈希值,通常是 128 位。MD5 不是加密算法,因为哈希值是不可逆的,即无法从哈希值还原出原始数据。

对称加密算法是一种使用相同密钥进行加密和解密的算法,例如 DES(Data Encryption Standard)、AES(Advanced Encryption Standard)等。与对称加密不同,哈希函数通常是单向的,只能从原始数据计算出哈希值,而无法从哈希值还原出原始数据。

安全性:MD5 已经被认为不再安全,因为它容易受到碰撞攻击。对于需要安全性的应用(如密码存储),建议使用更强的散列算法(如 SHA-256)和适当的安全实践(如加盐)。

性能:虽然 MD5 在性能上表现良好,但现代安全需求通常需要更强的散列算法。

MD5(Message Digest Algorithm 5)是一种广泛使用的加密散列函数,主要用于生成数据的唯一摘要值(哈希值)。MD5 的底层实现涉及多个复杂的步骤和算法。以下是 MD5 的底层工作原理和关键概念:

  1. 基本概念
    散列函数:MD5 是一种散列函数,用于将任意长度的输入数据(消息)映射为固定长度的输出(128 位,或 16 字节)的哈希值。
    不可逆性:MD5 生成的哈希值理论上无法逆推出原始输入数据。
    固定长度:无论输入数据的长度如何,MD5 总是生成一个 128 位的哈希值。
  2. MD5 的步骤
    MD5 的底层算法包括以下主要步骤:
  3. 初始化
    MD5 使用四个 32 位的初始常量(A、B、C、D)作为计www.chinasem.cn算的起始值:
    ( A = 0x67452301 )
    ( B = 0xEFCDAB89 )
    ( C = 0x98BADCFE )
    ( D = 0x10325476 )
    这些常量用于初始化 MD5 的内部状态。
  4. 填充
    将输入数据填充到 512 位的倍数。填充过程包括:
    填充位:在输入数据的末尾添加一个 1 位的标志位,表示数据结束。
    填充零:在标志位后添加零,直到数据长度接近 512 位。
    附加长度:在数据末尾附加原始数据的长度(以位为单位),以 64 位表示。填充后的数据总长度为 512 位的倍数。
  5. 数据分块
    将填充后的数据分成 512 位的块,每个块被进一步分成 16 个 32 位的子块(总共 64 个字节)。
  6. 处理每个数据块
    对于每个 512 位的数据块,执行以下步骤:
    扩展:将 16 个 32 位子块扩展为 64 个 32 位的子块,使用非线性函数进行处理。
    轮次:MD5 使用 64 轮的运算,每一轮使用不同的非线性函数(F、G、H、I)和常量(T[i])。每轮的运算包括:
    非线性函数:F(x, y, z)、G(x, y, z)、H(x, y, z)、I(x, y, z)
    常量:T[i] 是一组预定义的常量,与输入数据和轮次相关。
    位运算:使用位移和按位与、或、异或等运算来更新内部状态(A、B、C、D)。
    数据混合:将数据块与当前的内部状态进行混合。
  7. 输出
    将最后一个数据块的处理结果(A、B、C、D)连接起来,生成 128 位(16 字节)的哈希值。
  8. MD5 算法的详细步骤
    填充:
    在原始消息末尾添加 1 位的 1。
    添加足够的 0,使得消息长度(包括填充的部分)为 448 位(512 位的前 448 位),即还需填充 0 到 64 位数据块的长度。
    添加 64 位的消息长度,作为填充的最后部分,确保最终消息长度为 512 位的倍数。
    初始化变量:
    初始化 A、B、C、D 为常量值。
    处理数据块:
    将每个数据块分成 16 个 32 位的子块,使用特定的非线性函数和常量进行处理。
    进行 64 轮的运算,更新 A、B、C、D 的值。
    输出结果:
    将 A、B、C、D 的最终值转换为 128 位的哈希值,通常以 16 进制表示。
  9. MD5 的应用
    数据完整性检查:通过比较文件的 MD5 哈希值,可以检测文件是否被篡改。
    密码存储:在数据库中存储密码的 MD5 哈希值,而不是明文密码(注意:不建议仅使用 MD5 存储密码,因为它已被证明不够安全)。
  10. 安全性
    虽然 MD5 曾被广泛使用,但由于其安全性问题,如碰撞攻击(即不同的输入可以产生相同的哈希值),它已不再被认为是安全的。对于需要更高安全性的应用,建议使用更强的哈希函数,如 SHA-256 或 SHA-3。
    总结
    MD5 是一种将输入数据映射到固定长度哈希值的散列函数。其底层实现包括数据填充、分块、处理和最终输出四个主要步骤。尽管 MD5 在许多应用中曾被广泛使用,但由于安全性问题,现如今建议使用更安全的哈希算法。

Java 中实现 MD5 加密方式

这三种方法都能有效地生成 MD5 哈希。选择适合你项目需求的方式,如果已经使用了 Apache Commons Codec 或 Guava,可以直接利用它们的功能;如果只是简单的 MD5 加密需求,使用 MessageDigest 是最直接的方法。
在 Java 中实现 MD5 加密可以通过多种方式。

方法一:使用 MessageDigest

这是最基本的方式,使用 Java 内置的 MessageDigest 类。

示例代码:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5UsingMessageDigest {
    public static String md5(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] messageDigest = md.digest(input.getBytes());
            StringBuilder hexString = new StringBuilder();
            for (byte b : messageDigest) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        String input = "Hello, World!";
        System.out.println("MD5 Hash: " + md5(input));
    }
}

方法二:使用 Apache Commons Codec

Apache Commons Codec 是一个流行的库,提供了便捷的工具类进行编码和解码。

示例代码:

首先,确保在项目中添加 Apache Commons Codec 的依赖:

<dependency>
    <groupId>commons-codec</groupId>

    <artifactId>commons-codec</artifactId>

    <version>1.15</version> <!-- 检查最新版本 -->
</dependency>

然后可以使用以下代码:

import org.apache.commons.codec.digest.DigestUtils;

public class MD5UsingCommonsCodec {
    public static void main(String[] args) {
        String input = "Hello, World!";
        String md5Hash = DigestUtils.md5Hex(input);
        System.out.println("MD5 Hash: " + md5Hash);
    }
}

方法三:使用 Guava

Google 的 Guava 库也提供了简单的 MD5 加密功能。

示例代码:

首先,确保在项目中添加 Guava 的依赖:

<dependency>
    <groupId>com.google.guava</groupId>

    <artifactId>guava</artifactId>

    <version>31.0.1-jre</version> <!-- 检查最新版本 -->
</dependency>

然后可以使用以下代码:

import com.google.common.hash.Hashing;

import java.nio.charset.StandardCharsets;

public class MD5UsingGuava {
    public static void main(String[] args) {
        String input = "Hello, World!";
        String md5Hash = Hashing.md5()
                .hashString(input, StandardCharsets.UTF_8)
                .toString();
        System.out.println("MD5 Hash: " +javascript md5Hash);
    }
}

方法四:SPRING核心包

import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HashController {

    @GetMapping("/md5")
    public String getMD5(@RequestParam String input) {
        VMAPmXsnRreturn DigestUtils.md5DigestAsHex(input.getBytes());
    }
}

MD5Util

package com.maxvision.common.util;

import lombok.extern.slf4j.Slf4j;

import java.security.MessageDigest;

@Slf4j
public class MD5Util {
    private static String byteArrayToHexString(byte[] b) {
        StringBuilder resultSb = new StringBuilder();
        for (byte value : b) {
            resultSb.append(byteToHexString(value));
        }
        return resultSb.toString();
    }

    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0) {
            n += 256;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return HEX_DIGITS[d1] + HEX_DIGITS[d2];
    }

    /**
     * 用UTF8编码进行MD5加密
     *
     * @param origin 原字符串
     * @return 加密后字符串
     */
    public static String md5Encode(String origin) {
        return md5Encode(origin, "UTF-8");
    }

    public static String md5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = origin;
            MessageDigest md = MessageDigest.getInstance("MD5");
       android     if (charsetname == null || "".equals(charsetname)) {
                resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
            } else {
                resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
            }
        } catch (Exception ignored) {
www.chinasem.cn        }
        return resultString;
    }

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

以上就是Java实现MD5加密的四种方式的详细内容,更多关于Java MD5加密的资料请关注China编程(www.chinasem.cn)其它相关文章!

这篇关于Java实现MD5加密的四种方式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153815

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三