MD5 - 加密算法简要介绍与JAVA实现

简介: MD5 - 加密算法简要介绍与JAVA实现

【1】MD5是什么


MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。MD5是不可逆的。


该算法的文件号为:


RFC 1321(R.Rivest,MIT Laboratory for Computer Science and RSA Data Security Inc. April 1992)。


MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。除了MD5以外,其中比较有名的还有sha-1、RIPEMD以及Haval等。


对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。


128位散列值转换为16进制字符串为32个字符。即,加密后的结果为32位16进制的字符串。


经典的哈希(散列)算法还有:MD2、MD4 和 SHA-1(目的是将任意长输入通过算法变为固定长输出,且保证输入变化一点输出都不同,且不能反向解密)。


【2】MD5的特点

① 长度固定


不管多长的字符串,加密后长度都是一样长,方便平时信息的统计和管理。


② 容易计算


从原数据计算出MD5值很容易。


③ 抗修改性


对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。


④ 强抗碰撞


已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的(并非不可以)。

【3】MD5加密过程

第一种,加密字符串

① 获取信息摘要对象:md5


通过信息摘要单例的构造函数获取:

MessageDigest md5 = MessageDigest.getInstance("MD5");


② 获取摘要字节数组

两种方式:

byte[] bytes = str.getBytes();
byte[] digest = md5.digest(bytes);
byte[] bytes = str.getBytes();
md5.update(bytes);
byte[] digest = md5.digest();


③ 把摘要数组中的每一个字节转换成16进制,并拼在一起就得到了MD5值.


第二种,加密文件


方法传入的是文件对象 : file


① 因为是文件不是方法,所以不是像刚才那样通过摘要获取字符串。


② 使用到另一个方法即可:就是信息摘要对象更新:md5.update(byte[] input)方法,用法是通过读取流,不断的更新从流中读到的"信息数组"。


③ 然后通过”信息摘要对象”获取摘要,不用参数:md5.digest(),此时返回的数组就已经是包含内容的摘要数组了。


④ 把摘要数组中的每一个字节转换成16进制,并拼在一起就得到了MD5值。


同样来源除了文件还可以是url,过程同上。


【4】MD5工具类

package com.web.encrypt;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Util {
  // 用来将字节转换成 16 进制表示的字符
  private static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd','e', 'f' };
  protected static MessageDigest messagedigest = null;
  static {
    try {
      messagedigest = MessageDigest.getInstance("MD5");
    } catch (NoSuchAlgorithmException nsaex) {
      System.err.println(MD5Util.class.getName()
          + "初始化失败,MessageDigest不支持MD5Util。");
      nsaex.printStackTrace();
    }
  }
  // 加密字符串
  public static String getMD5(String str){
    byte[] bs = str.getBytes();
    return getMD5FromByte(bs);
  }
  private static String getMD5FromByte(byte[] source) {
    String s = null;
    try {
      java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
      md.update(source);
      byte tmp[] = messagedigest.digest();
      // MD5 的计算结果是一个 128 位的长整数(16个字节),转为16进制则为32个字符
      char str[] = new char[16 * 2]; 
  // 每个字节用 16 进制表示的话,使用两个字符(一个8位->2个4位->2个16进制字符),所以表示成 16 进制需要 32 个字符
      int k = 0; // 表示转换结果中对应的字符位置
      for (int i = 0; i < 16; i++) { 
        // 从第一个字节开始,对 MD5 的每一个字节
        // 转换成 16 进制字符的转换
        byte byte0 = tmp[i]; // 取第 i 个字节
        str[k++] = hexDigits[byte0 >>> 4 & 0xf];
         // 取字节中高 4 位的数字转换,>>>为逻辑右移,将符号位一起右移
        str[k++] = hexDigits[byte0 & 0xf];
         // 取字节中低 4 位的数字转换
      }
      s = new String(str); 
      // 换后的结果转换为字符串
    } catch (Exception e) {
      e.printStackTrace();
    }
    return s;
  }
  // 加密文件对象
  public static String getFileMD5String(File file) throws FileNotFoundException {  
    String value = null;  
    FileInputStream in = new FileInputStream(file);  
    try {  
      MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());  
      MessageDigest md5 = MessageDigest.getInstance("MD5");  
      md5.update(byteBuffer);  
      BigInteger bi = new BigInteger(1, md5.digest());  
      value = bi.toString(16);  
    } catch (Exception e) {  
      e.printStackTrace();  
    } finally {  
      if(null != in) {  
        try {  
          in.close();  
        } catch (IOException e) {  
          e.printStackTrace();  
        }  
      }  
    }  
    return value;  
  }  
  //参数为文件路径
  public static String getFileMD5String(String  filePath) throws FileNotFoundException {  
          String value = null;  
          File file=new File(filePath);
          FileInputStream in = new FileInputStream(file);  
      try {  
          MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());  
          MessageDigest md5 = MessageDigest.getInstance("MD5");  
          md5.update(byteBuffer);  
          BigInteger bi = new BigInteger(1, md5.digest());  
          value = bi.toString(16);  
      } catch (Exception e) {  
          e.printStackTrace();  
      } finally {  
              if(null != in) {  
                  try {  
                  in.close();  
              } catch (IOException e) {  
                  e.printStackTrace();  
              }  
          }  
      }  
         return value;  
      }  
  //参数为url
  public static String getFileMD5StringByURL(String urlString) throws IOException {   
    URL url = new URL(urlString);
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    BufferedInputStream fis = null;
    fis = new BufferedInputStream(connection.getInputStream());
    byte[] buffer = new byte[1024];
    int numRead = 0;
    while ((numRead = fis.read(buffer)) > 0) {
      messagedigest.update(buffer, 0, numRead);
    }
    fis.close();
    return bufferToHex(messagedigest.digest());
  }
  //参数为字节数组
  public static String getMD5String(byte[] bytes) {
    messagedigest.update(bytes);
    return bufferToHex(messagedigest.digest());
  }
  // 将字节数组转换为16进制的字符串
  private static String bufferToHex(byte bytes[]) {
    int m = 0;
    int n = bytes.length;
    StringBuffer stringbuffer = new StringBuffer(2 * n);
    int k = m + n;
    for (int l = m; l < k; l++) {
      appendHexPair(bytes[l], stringbuffer);
    }
    return stringbuffer.toString();
  }
  private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
    char c0 = hexDigits[(bt & 0xf0) >> 4];
    // 取字节中高 4 位的数字转换, >>> 为逻辑右移,将符号位一起右移
    char c1 = hexDigits[bt & 0xf];
    // 取字节中低 4 位的数字转换 
    stringbuffer.append(c0);
    stringbuffer.append(c1);
  }
}
目录
相关文章
|
27天前
|
机器学习/深度学习 人工智能 资源调度
大语言模型的核心算法——简要解析
大语言模型的核心算法基于Transformer架构,以自注意力机制为核心,通过Q、K、V矩阵动态捕捉序列内部关系。多头注意力增强模型表达能力,位置编码(如RoPE)解决顺序信息问题。Flash Attention优化计算效率,GQA平衡性能与资源消耗。训练上,DPO替代RLHF提升效率,MoE架构实现参数扩展,Constitutional AI实现自监督对齐。整体技术推动模型在长序列、低资源下的性能突破。
204 8
|
5月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
5月前
|
存储 缓存 监控
上网行为监控系统剖析:基于 Java LinkedHashMap 算法的时间序列追踪机制探究
数字化办公蓬勃发展的背景下,上网行为监控系统已成为企业维护信息安全、提升工作效能的关键手段。该系统需实时记录并深入分析员工的网络访问行为,如何高效存储和管理这些处于动态变化中的数据,便成为亟待解决的核心问题。Java 语言中的LinkedHashMap数据结构,凭借其独有的有序性特征以及可灵活配置的淘汰策略,为上网行为监控系统提供了一种兼顾性能与功能需求的数据管理方案。本文将对LinkedHashMap在上网行为监控系统中的应用原理、实现路径及其应用价值展开深入探究。
109 3
|
5月前
|
人工智能 算法 NoSQL
LRU算法的Java实现
LRU(Least Recently Used)算法用于淘汰最近最少使用的数据,常应用于内存管理策略中。在Redis中,通过`maxmemory-policy`配置实现不同淘汰策略,如`allkeys-lru`和`volatile-lru`等,采用采样方式近似LRU以优化性能。Java中可通过`LinkedHashMap`轻松实现LRUCache,利用其`accessOrder`特性和`removeEldestEntry`方法完成缓存淘汰逻辑,代码简洁高效。
206 0
|
4月前
|
存储 算法 安全
Java中的对称加密算法的原理与实现
本文详细解析了Java中三种常用对称加密算法(AES、DES、3DES)的实现原理及应用。对称加密使用相同密钥进行加解密,适合数据安全传输与存储。AES作为现代标准,支持128/192/256位密钥,安全性高;DES采用56位密钥,现已不够安全;3DES通过三重加密增强安全性,但性能较低。文章提供了各算法的具体Java代码示例,便于快速上手实现加密解密操作,帮助用户根据需求选择合适的加密方案保护数据安全。
351 58
|
3月前
|
存储 负载均衡 算法
我们来说一说 Java 的一致性 Hash 算法
我是小假 期待与你的下一次相遇 ~
116 1
|
3月前
|
存储 监控 算法
企业上网监控场景下布隆过滤器的 Java 算法构建及其性能优化研究
布隆过滤器是一种高效的数据结构,广泛应用于企业上网监控系统中,用于快速判断员工访问的网址是否为违规站点。相比传统哈希表,它具有更低的内存占用和更快的查询速度,支持实时拦截、动态更新和资源压缩,有效提升系统性能并降低成本。
76 0
|
4月前
|
存储 Java 数据安全/隐私保护
Java技术栈揭秘:Base64加密和解密文件的实战案例
以上就是我们今天关于Java实现Base64编码和解码的实战案例介绍。希望能对你有所帮助。还有更多知识等待你去探索和学习,让我们一同努力,继续前行!
333 5
|
6月前
|
存储 机器学习/深度学习 监控
如何监控员工的电脑——基于滑动时间窗口的Java事件聚合算法实现探析​
在企业管理场景中,如何监控员工的电脑操作行为是一个涉及效率与合规性的重要课题。传统方法依赖日志采集或屏幕截图,但数据量庞大且实时性不足。本文提出一种基于滑动时间窗口的事件聚合算法,通过Java语言实现高效、低资源占用的监控逻辑,为如何监控员工的电脑提供一种轻量化解决方案。
138 3
|
8月前
|
存储 缓存 Java
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
819 3
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡

热门文章

最新文章