首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >MessageDigest 详解

MessageDigest 详解

作者头像
全栈程序员站长
发布2022-07-02 14:53:15
发布2022-07-02 14:53:15
1.2K0
举报

大家好,又见面了,我是你们的朋友全栈君。

一、概述

java.security. MessageDigest 类用于为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。简单点说就是用于生成 散列码。 信息摘要是安全的单向哈希函数,它接收任意大小的数据,输出固定长度的哈希值。关于 信息摘要 和 散列码 请参照《 数字证书简介

MessageDigest 通过其getInstance系列静态函数来进行实例化和初始化。MessageDigest 对象通过使用 update 方法处理数据。任何时候都可以调用 reset 方法重置摘要。一旦所有需要更新的数据都已经被更新了,应该调用 digest 方法之一完成哈希计算并返回结果。

对于给定数量的更新数据,digest 方法只能被调用一次。digest 方法被调用后,MessageDigest 对象被重新设置成其初始状态。

MessageDigest 的实现可随意选择是否实现 Cloneable 接口。客户端应用程可以通过尝试复制和捕获 CloneNotSupportedException 测试可复制性:

代码语言:javascript
复制
 MessageDigest md = MessageDigest.getInstance("SHA"); try {         md.update(toChapter1);     MessageDigest tc1 = md.clone();     byte[] toChapter1Digest = tc1.digest();     md.update(toChapter2);     ...etc. } catch (CloneNotSupportedException cnse) {         throw new DigestException("couldn't make digest of partial content"); }

注意1:即时给定MessageDigest的实现是不可复制的,则仍然能够通过getInstance方法实例化几个实例计算来同时进行摘要信息的计算。

注意2:由于历史原因,此类是抽象的,是从 MessageDigestSpi 扩展的。应用程序开发人员只应该注意在此 MessageDigest 类中定义的方法;超类中的所有方法是供希望提供自己的信息摘要算法实现的加密服务提供者使用的。

注意3:MessageDigest并不是单实例的。如下代码所示:

代码语言:javascript
复制
         try            {                    MessageDigest mdTemp1 = MessageDigest.getInstance("MD5");                MessageDigest mdTemp2= MessageDigest.getInstance("MD5");                MessageDigest mdTemp3= MessageDigest.getInstance("MD5");                System.out.println("mdTemp1==mdTemp2?:"+(mdTemp1==mdTemp2));                System.out.println("mdTemp2==mdTemp3?:"+(mdTemp2==mdTemp3));            } catch (NoSuchAlgorithmException e)            {                    // TODO Auto-generated catch block                e.printStackTrace();            }

运行结果

代码语言:javascript
复制
mdTemp1==mdTemp2?:falsemdTemp2==mdTemp3?:false

构造方法摘要

protected

MessageDigest(String algorithm) 创建具有指定算法名称的MessageDigest 实例对象。

二、实际实践

2.1、创建 MessageDigest 对象 计算信息摘(即 散列码 )要做的第一步是创建 MessageDigest 对象 实例。像所有的引擎类一样,获取某类报文摘要算法(即 散列算法 ,比如 MD5 )的 MessageDigest 对象的途径是调用 MessageDigest 类中的 getInstance 静态 factory 方法:

代码语言:javascript
复制
    public static MessageDigest getInstance(String algorithm)

注意:算法名不区分大小写。例如,以下所有调用都是相等的:

代码语言:javascript
复制
     MessageDigest
     
     
     .
     
     
     getInstance
     
     
     (
     
     
     "SHA"
     
     
     );
    
    
    
    
    
    
     
     
     MessageDigest
     
     
     .
     
     
     getInstance
     
     
     (
     
     
     "sha"
     
     
     );
    
    
    
    
    
    
     
     
     MessageDigest
     
     
     .
     
     
     getInstance
     
     
     (
     
     
     "sHa"
     
     
     );

调用程序可选择指定提供者名称,以保证所要求的算法是由已命名提供者实现的:

代码语言:javascript
复制
public static MessageDigest getInstance(String algorithm, String provider);

调用 getInstance 将返回已初始化过的 MessageDigest对象。因此,它不需要进一步的初始化。

2.2、向 MessageDigest 传送要计算的数据

计算数据的摘要的第二步是向已初始化的 MessageDigest对象提供传送要计算的数据。这将通过一次或多次调用以下某个 update(更新)方法来完成:

代码语言:javascript
复制
     public
     
     
      
     
     
     void
     
     
      update
     
     
     (
     
     
     byte
     
     
      input
     
     
     );
    
    
    
    
    
    
     
     
     public
     
     
      
     
     
     void
     
     
      update
     
     
     (
     
     
     byte
     
     
     []
     
     
      input
     
     
     );
    
    
    
    
    
    
     
     
     public
     
     
      
     
     
     void
     
     
      update
     
     
     (
     
     
     byte
     
     
     []
     
     
      input
     
     
     ,
     
     
      
     
     
     int
     
     
      offset
     
     
     ,
     
     
      
     
     
     int
     
     
      len
     
     
     );

2.3、计算摘要

通过调用 update 方法向 MessageDigest对象 提传送要计算的数据后,你就可以调用以下某个 digest(摘要)方法来计算摘要(即 生成 散列码):

代码语言:javascript
复制
     public
     
     
      
     
     
     byte
     
     
     []
     
     
      digest
     
     
     ();
    
    
    
    
    
    
     
     
     public
     
     
      
     
     
     byte
     
     
     []
     
     
      digest
     
     
     (
     
     
     byte
     
     
     []
     
     
      input
     
     
     );
    
    
    
    
    
    
     
     
     public
     
     
      
     
     
     int
     
     
      digest
     
     
     (
     
     
     byte
     
     
     []
     
     
      buf
     
     
     ,
     
     
      
     
     
     int
     
     
      offset
     
     
     ,
     
     
      
     
     
     int
     
     
      len
     
     
     );

前两个方法返回计算出的摘要。后一个方法把计算出的摘要储存在所提供的 buf 缓冲区中,起点是 offset。len 是 buf 中分配给该摘要的字节数。该方法返回实际存储在 buf 中的字节数。

对第二个接受输入字节数组变量的 digest 方法的调用等价于用指定的输入调用:

代码语言:javascript
复制
    public void update(byte[] input)

,接着调用不带参数的 digest 方法.

三、例子演示

3.1、★ 编程思路:

java.security包中的 MessageDigest类提供了计算消息摘要 ( 即生成 散列码 )的方法,首先生成对象,执行其 update( )方法可

以将原始数据传递给该对象,然后执行其 digest( )方法即可得到消息摘要。具体步骤如下:

(1)生成MessageDigest对象

代码语言:javascript
复制
MessageDigest m=MessageDigest.getInstance("MD5");

MessageDigest类也是一个工厂类,其构造器是受保护的,不允许

直接使用new MessageDigist( )来创建对象,而必须通过其静态方法 getInstance( )生成 MessageDigest对象。

其中传入的参数指定计算消息摘要所使用的算法,常用的有” MD5“,” SHA“等。

(2)传入需要计算的字符串

代码语言:javascript
复制
m.update(x.getBytes("UTF8" ));

分析:x为需要计算的字符串,update传入的参数是字节类型或字节类型数组,对于字符串,需要先使用getBytes( )方法生成字符串数组。

(3)计算消息摘要

代码语言:javascript
复制
byte s[ ]=m.digest( );

分析:执行MessageDigest对象的digest( )方法完成计算,计算的结果通过字节类型的数组返回。

(4)处理计算结果

必要的话可以使用如下代码将计算结果(byte数组)转换为字符串。

代码语言:javascript
复制
    static
    
    
     
    
    
    String
    
    
     convertToHexString
    
    
    (
    
    
    byte
    
    
     data
    
    
    [])
    
    
     
    
    
    { 
     
   
   
   
   
   
   
    
    
     
    
    
    StringBuffer
    
    
     strBuffer 
    
    
    =
    
    
     
    
    
    new
    
    
     
    
    
    StringBuffer
    
    
    ();
   
   
   
   
   
   
    
    
     
    
    
    for
    
    
     
    
    
    (
    
    
    int
    
    
     i 
    
    
    =
    
    
     
    
    
    0
    
    
    ;
    
    
     i 
    
    
    <
    
    
     data
    
    
    .
    
    
    length
    
    
    ;
    
    
     i
    
    
    ++)
    
    
     
    
    
    { 
     
   
   
   
   
   
   
    
    
     
    
    
    strBuffer
    
    
    .
    
    
    append
    
    
    (
    
    
    Integer
    
    
    .
    
    
    toHexString
    
    
    (
    
    
    0xff
    
    
     
    
    
    &
    
    
     data
    
    
    [
    
    
    i
    
    
    ]));
   
   
   
   
   
   
    
    
     
    
    
    }
   
   
   
   
   
   
    
    
     
    
    
    return
    
    
     strBuffer
    
    
    .
    
    
    toString
    
    
    ();
   
   
   
   
   
   
    
    
     
    
    
    }

3.2、示例一

★完整程序如下:

代码语言:javascript
复制
    public
    
    
     
    
    
    class
    
    
     
    
    
    MessageDigestDemo
    
    
     
    
    
    extends
    
    
     
    
    
    Thread
    
    
     
    
    
    { 
     
   
   
   
   
   
   
    
    
     
    
    
    public
    
    
     
    
    
    void
    
    
     run
    
    
    ()
    
    
     
    
    
    { 
     
   
   
   
   
   
   
    
    
     
    
    
    String
    
    
     text 
    
    
    =
    
    
     
    
    
    "abc"
    
    
    ;
   
   
   
   
   
   
    
    
     
    
    
    byte
    
    
     data
    
    
    []
    
    
     
    
    
    =
    
    
     
    
    
    null
    
    
    ;
   
   
   
   
   
   
    
    
     
    
    
    MessageDigest
    
    
     m
    
    
    ;
   
   
   
   
   
   
    
    
     
    
    
    try
    
    
     
    
    
    { 
     
   
   
   
   
   
   
    
    
     
    
    
    data 
    
    
    =
    
    
     text
    
    
    .
    
    
    getBytes
    
    
    (
    
    
    "UTF8"
    
    
    );
   
   
   
   
   
   
    
    
     
    
    
    m 
    
    
    =
    
    
     
    
    
    MessageDigest
    
    
    .
    
    
    getInstance
    
    
    (
    
    
    "MD5"
    
    
    );
   
   
   
   
   
   
    
    
     
    
    
    m
    
    
    .
    
    
    update
    
    
    (
    
    
    data
    
    
    );
   
   
   
   
   
   
    
    
     
    
    
    byte
    
    
     resultData
    
    
    []
    
    
     
    
    
    =
    
    
     m
    
    
    .
    
    
    digest
    
    
    ();
   
   
   
   
   
   
    
    
     
    
    
    System
    
    
    .
    
    
    out
    
    
    .
    
    
    println
    
    
    (
    
    
    convertToHexString
    
    
    (
    
    
    resultData
    
    
    ));
   
   
   
   
   
   
    
    
     
    
    
    }
    
    
     
    
    
    catch
    
    
     
    
    
    (
    
    
    NoSuchAlgorithmException
    
    
     e
    
    
    )
    
    
     
    
    
    { 
     
   
   
   
   
   
   
    
    
     
    
    
    // TODO Auto-generated catch block
   
   
   
   
   
   
    
    
     
    
    
    e.printStackTrace();
   
   
   
   
   
   
    
    
     
    
    
    } catch (UnsupportedEncodingException e) { 
     
   
   
   
   
   
   
    
    
     
    
    
    // TODO Auto-generated catch block
   
   
   
   
   
   
    
    
     
    
    
    e.printStackTrace();
   
   
   
   
   
   
    
    
     
    
    
    }
   
   
   
   
   
   

   
   
   
   
   
   
    
    
     
    
    
    }
   
   
   
   
   
   

   
   
   
   
   
   
    
    
     
    
    
    static
    
    
     
    
    
    String
    
    
     convertToHexString
    
    
    (
    
    
    byte
    
    
     data
    
    
    [])
    
    
     
    
    
    { 
     
   
   
   
   
   
   
    
    
     
    
    
    StringBuffer
    
    
     strBuffer 
    
    
    =
    
    
     
    
    
    new
    
    
     
    
    
    StringBuffer
    
    
    ();
   
   
   
   
   
   
    
    
     
    
    
    for
    
    
     
    
    
    (
    
    
    int
    
    
     i 
    
    
    =
    
    
     
    
    
    0
    
    
    ;
    
    
     i 
    
    
    <
    
    
     data
    
    
    .
    
    
    length
    
    
    ;
    
    
     i
    
    
    ++)
    
    
     
    
    
    { 
     
   
   
   
   
   
   
    
    
     
    
    
    strBuffer
    
    
    .
    
    
    append
    
    
    (
    
    
    Integer
    
    
    .
    
    
    toHexString
    
    
    (
    
    
    0xff
    
    
     
    
    
    &
    
    
     data
    
    
    [
    
    
    i
    
    
    ]));
   
   
   
   
   
   
    
    
     
    
    
    }
   
   
   
   
   
   
    
    
     
    
    
    return
    
    
     strBuffer
    
    
    .
    
    
    toString
    
    
    ();
   
   
   
   
   
   
    
    
     
    
    
    }
   
   
   
   
   
   
    
    
    }

★运行结果

代码语言:javascript
复制
900150983cd24fb0d6963f7d28e17f72

3.3、示例二

在这里我们将对计算生成的md5使用 sun.misc.BASE64Encoder进行简单的加密。

代码语言:javascript
复制
    public
    
    
     
    
    
    String
    
    
     md5sumWithEncoder
    
    
    (
    
    
    String
    
    
     text
    
    
    )
    
    
     
    
    
    throws
    
    
     
    
    
    NoSuchAlgorithmException
    
    
    ,
    
    
     
   
   
   
   
   
   
    
    
    UnsupportedEncodingException
    
    
    { 
     
   
   
   
   
   
   
    
    
            
    
    
    /*确定计算方法*/
   
   
   
   
   
   
    
    
            
    
    
    MessageDigest
    
    
     md5
    
    
    =
    
    
    MessageDigest
    
    
    .
    
    
    getInstance
    
    
    (
    
    
    "MD5"
    
    
    );
   
   
   
   
   
   
    
    
            BASE64Encoder base64en 
    
    
    =
    
    
     
    
    
    new
    
    
     BASE64Encoder
    
    
    ();
   
   
   
   
   
   
    
    
            
    
    
    /*加密后的散列码字符串*/
   
   
   
   
   
   
    
    
            
    
    
    String
    
    
     strMd5
    
    
    =
    
    
    base64en
    
    
    .
    
    
    encode
    
    
    (
    
    
    md5
    
    
    .
    
    
    digest
    
    
    (
    
    
    text
    
    
    .
    
    
    getBytes
    
    
    (
    
    
    "utf-8"
    
    
    )));
   
   
   
   
   
   
    
    
            
    
    
    return
    
    
     strMd5
    
    
    ;
   
   
   
   
   
   
    
    
        
    
    
    }

调用函数

代码语言:javascript
复制
    String
    
    
     str
    
    
    =
    
    
    "0123456789"
   
   
   
   
   
   
    
    
     
    
    
    System
    
    
    .
    
    
    out
    
    
    .
    
    
    println
    
    
    (
    
    
    md5sumWithEncoder
    
    
    (
    
    
    str
    
    
    ));

输出

eB5eJF1ptWaXm4bijSPyxw==

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/148135.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档