MessageDigest详解

发布时间:2025-12-09 14:07:18 浏览次数:5

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

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

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

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

<p ><span ></span><span  >MessageDigest</span><span > md </span><span  >=</span><span > </span><span  >MessageDigest</span><span  >.</span><span >getInstance</span><span  >(</span><span  >"SHA"</span><span  >);</span></p><p ><span ></span><span  >try</span><span > </span><span  >{</span></p><p ><span >  md</span><span  >.</span><span >update</span><span  >(</span><span >toChapter1</span><span  >);</span></p><p ><span >  </span><span  >MessageDigest</span><span > tc1 </span><span  >=</span><span > md</span><span  >.</span><span >clone</span><span  >();</span></p><p ><span >  </span><span  >byte</span><span  >[]</span><span > toChapter1Digest </span><span  >=</span><span > tc1</span><span  >.</span><span >digest</span><span  >();</span></p><p ><span >  md</span><span  >.</span><span >update</span><span  >(</span><span >toChapter2</span><span  >);</span></p><p ><span >  </span><span  >...</span><span >etc</span><span  >.</span></p><p ><span ></span><span  >}</span><span > </span><span  >catch</span><span > </span><span  >(</span><span  >CloneNotSupportedException</span><span > cnse</span><span  >)</span><span > </span><span  >{</span></p><p ><span >  </span><span  >throw</span><span > </span><span  >new</span><span > </span><span  >DigestException</span><span  >(</span><span  >"couldn't make digest of partial content"</span><span  >);</span></p><p ><span ></span><span  >}</span></p>

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

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

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

<p ><span > </span><span >    </span><span  >try</span></p><p ><span >      </span><span  >{</span></p><p ><span >        </span><span  >MessageDigest</span><span > mdTemp1 </span><span  >=</span><span > </span><span  >MessageDigest</span><span  >.</span><span >getInstance</span><span  >(</span><span  >"MD5"</span><span  >);</span></p><p ><span >        </span><span  >MessageDigest</span><span > mdTemp2</span><span  >=</span><span > </span><span  >MessageDigest</span><span  >.</span><span >getInstance</span><span  >(</span><span  >"MD5"</span><span  >);</span></p><p ><span >        </span><span  >MessageDigest</span><span > mdTemp3</span><span  >=</span><span > </span><span  >MessageDigest</span><span  >.</span><span >getInstance</span><span  >(</span><span  >"MD5"</span><span  >);</span></p><p ><span >        </span><span  >System</span><span  >.</span><span  >out</span><span  >.</span><span >println</span><span  >(</span><span  >"mdTemp1==mdTemp2?:"</span><span  >+(</span><span >mdTemp1</span><span  >==</span><span >mdTemp2</span><span  >));</span></p><p ><span >        </span><span  >System</span><span  >.</span><span  >out</span><span  >.</span><span >println</span><span  >(</span><span  >"mdTemp2==mdTemp3?:"</span><span  >+(</span><span >mdTemp2</span><span  >==</span><span >mdTemp3</span><span  >));</span></p><p ><span >      </span><span  >}</span><span > </span><span  >catch</span><span > </span><span  >(</span><span  >NoSuchAlgorithmException</span><span > e</span><span  >)</span></p><p ><span >      </span><span  >{</span></p><p ><span >        </span><span  >// TODO Auto-generated catch block</span></p><p ><span  >        e.printStackTrace();</span></p><p ><span  >      }</span></p>

运行结果

<p ><span >mdTemp1</span><span  >==</span><span >mdTemp2</span><span  >?:</span><span >false</span></p><p ><span >mdTemp2</span><span  >==</span><span >mdTemp3</span><span  >?:</span><span  >false</span></p>
构造方法摘要
protectedMessageDigest(Stringalgorithm)
创建具有指定算法名称的MessageDigest实例对象。
2.1、创建
MessageDigest
对象 计算信息摘(即 散列码 )要做的第一步是创建
MessageDigest
对象 实例。像所有的引擎类一样,获取某类报文摘要算法(即
散列算法 ,比如
MD5 )的
MessageDigest 对象的途径是调用
MessageDigest 类中的
getInstance 静态
factory 方法:
<p ><span >  </span><span  >public</span><span > </span><span  >static</span><span > </span><span  >MessageDigest</span><span > getInstance</span><span  >(</span><span  >String</span><span > algorithm</span><span  >)</span></p>

注意:算法名不区分大小写。例如,以下所有调用都是相等的:
<p><span  >MessageDigest</span><span  >.</span><span >getInstance</span><span  >(</span><span  >"SHA"</span><span  >);</span></p><p><span  >MessageDigest</span><span  >.</span><span >getInstance</span><span  >(</span><span  >"sha"</span><span  >);</span></p><p><span  >MessageDigest</span><span  >.</span><span >getInstance</span><span  >(</span><span  >"sHa"</span><span  >);</span></p>

调用程序可选择指定提供者名称,以保证所要求的算法是由已命名提供者实现的:
<p ><span  >public</span><span > </span><span  >static</span><span > </span><span  >MessageDigest</span><span > getInstance</span><span  >(</span><span  >String</span><span > algorithm</span><span  >,</span><span > </span><span  >String</span><span > provider</span><span  >);</span></p>

调用 getInstance 将返回已初始化过的
MessageDigest对象。因此,它不需要进一步的初始化。 2.2、向
MessageDigest
传送要计算的数据 计算数据的摘要的第二步是向已初始化的
MessageDigest对象提供传送要计算的数据。这将通过一次或多次调用以下某个
update(更新)方法来完成:
<p><span  >public</span><span > </span><span  >void</span><span > update</span><span  >(</span><span  >byte</span><span > input</span><span  >);</span></p><p><span  >public</span><span > </span><span  >void</span><span > update</span><span  >(</span><span  >byte</span><span  >[]</span><span > input</span><span  >);</span></p><p><span  >public</span><span > </span><span  >void</span><span > update</span><span  >(</span><span  >byte</span><span  >[]</span><span > input</span><span  >,</span><span > </span><span  >int</span><span > offset</span><span  >,</span><span > </span><span  >int</span><span > len</span><span  >);</span></p>

2.3、计算摘要 通过调用 update 方法向
MessageDigest对象
提传送要计算的数据后,你就可以调用以下某个 digest(摘要)方法来计算摘要(即
生成 散列码):
<p><span  >public</span><span > </span><span  >byte</span><span  >[]</span><span > digest</span><span  >();</span></p><p><span  >public</span><span > </span><span  >byte</span><span  >[]</span><span > digest</span><span  >(</span><span  >byte</span><span  >[]</span><span > input</span><span  >);</span></p><p><span  >public</span><span > </span><span  >int</span><span > digest</span><span  >(</span><span  >byte</span><span  >[]</span><span > buf</span><span  >,</span><span > </span><span  >int</span><span > offset</span><span  >,</span><span > </span><span  >int</span><span > len</span><span  >);</span></p>

前两个方法返回计算出的摘要。后一个方法把计算出的摘要储存在所提供的 buf 缓冲区中,起点是 offset。len 是 buf 中分配给该摘要的字节数。该方法返回实际存储在 buf 中的字节数。 对第二个接受输入字节数组变量的 digest 方法的调用等价于用指定的输入调用:
<p ><span >  </span><span  >public</span><span > </span><span  >void</span><span > update</span><span  >(</span><span  >byte</span><span  >[]</span><span > input</span><span  >)</span></p>

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

三、例子演示

3.1、★ 编程思路: java.security包中的
MessageDigest类提供了计算消息摘要

即生成 散列码
)的方法,首先生成对象,执行其
update( )方法可 以将原始数据传递给该对象,然后执行其
digest( )方法即可得到消息摘要。具体步骤如下: (1)生成MessageDigest对象
<p ><span  >MessageDigest</span><span > m</span><span  >=</span><span  >MessageDigest</span><span  >.</span><span >getInstance</span><span  >(</span><span  >"MD5"</span><span  >);</span></p>

MessageDigest类也是一个工厂类,其构造器是受保护的,不允许 直接使用new MessageDigist( )来创建对象,而必须通过其静态方法
getInstance( )生成
MessageDigest对象。 其中传入的参数指定计算消息摘要所使用的算法,常用的有”
MD5“,”
SHA“等。 (2)传入需要计算的字符串
<p ><span >m</span><span  >.</span><span >update</span><span  >(</span><span >x</span><span  >.</span><span >getBytes</span><span  >(</span><span  >"UTF8"</span><span > </span><span  >));</span></p>

分析:x为需要计算的字符串,update传入的参数是字节类型或字节类型数组,对于字符串,需要先使用getBytes( )方法生成字符串数组。 (3)计算消息摘要
<p ><span  >byte</span><span > s</span><span  >[</span><span > </span><span  >]=</span><span >m</span><span  >.</span><span >digest</span><span  >(</span><span > </span><span  >);</span></p>

分析:执行MessageDigest对象的digest( )方法完成计算,计算的结果通过字节类型的数组返回。 (4)处理计算结果 必要的话可以使用如下代码将计算结果(byte数组)转换为字符串。
<p><span > </span><span  >static</span><span > </span><span  >String</span><span > convertToHexString</span><span  >(</span><span  >byte</span><span > data</span><span  >[])</span><span > </span><span  >{</span></p><p><span >  </span><span  >StringBuffer</span><span > strBuffer </span><span  >=</span><span > </span><span  >new</span><span > </span><span  >StringBuffer</span><span  >();</span></p><p><span >  </span><span  >for</span><span > </span><span  >(</span><span  >int</span><span > i </span><span  >=</span><span > </span><span  >0</span><span  >;</span><span > i </span><span  ><</span><span > data</span><span  >.</span><span >length</span><span  >;</span><span > i</span><span  >++)</span><span > </span><span  >{</span></p><p><span >   </span><span >strBuffer</span><span  >.</span><span >append</span><span  >(</span><span  >Integer</span><span  >.</span><span >toHexString</span><span  >(</span><span  >0xff</span><span > </span><span  >&</span><span > data</span><span  >[</span><span >i</span><span  >]));</span></p><p><span >  </span><span  >}</span></p><p><span >  </span><span  >return</span><span > strBuffer</span><span  >.</span><span >toString</span><span  >();</span></p><p><span > </span><span  >}</span></p>

3.2、示例一 ★完整程序如下:
<p><span  >public</span><span > </span><span  >class</span><span > </span><span  >MessageDigestDemo</span><span > </span><span  >extends</span><span > </span><span  >Thread</span><span > </span><span  >{</span></p><p><span > </span><span  >public</span><span > </span><span  >void</span><span > run</span><span  >()</span><span > </span><span  >{</span></p><p><span > </span><span  >String</span><span > text </span><span  >=</span><span > </span><span  >"abc"</span><span  >;</span></p><p><span > </span><span  >byte</span><span > data</span><span  >[]</span><span > </span><span  >=</span><span > </span><span  >null</span><span  >;</span></p><p><span > </span><span  >MessageDigest</span><span > m</span><span  >;</span></p><p><span > </span><span  >try</span><span > </span><span  >{</span></p><p><span > </span><span >data </span><span  >=</span><span > text</span><span  >.</span><span >getBytes</span><span  >(</span><span  >"UTF8"</span><span  >);</span></p><p><span > </span><span >m </span><span  >=</span><span > </span><span  >MessageDigest</span><span  >.</span><span >getInstance</span><span  >(</span><span  >"MD5"</span><span  >);</span></p><p><span > </span><span >m</span><span  >.</span><span >update</span><span  >(</span><span >data</span><span  >);</span></p><p><span > </span><span  >byte</span><span > resultData</span><span  >[]</span><span > </span><span  >=</span><span > m</span><span  >.</span><span >digest</span><span  >();</span></p><p><span > </span><span  >System</span><span  >.</span><span  >out</span><span  >.</span><span >println</span><span  >(</span><span >convertToHexString</span><span  >(</span><span >resultData</span><span  >));</span></p><p><span > </span><span  >}</span><span > </span><span  >catch</span><span > </span><span  >(</span><span  >NoSuchAlgorithmException</span><span > e</span><span  >)</span><span > </span><span  >{</span></p><p><span > </span><span  >// TODO Auto-generated catch block</span></p><p><span  > </span><span  >e.printStackTrace();</span></p><p><span  > </span><span  >} catch (UnsupportedEncodingException e) {</span></p><p><span  > </span><span  >// TODO Auto-generated catch block</span></p><p><span  > </span><span  >e.printStackTrace();</span></p><p><span  > </span><span  >}</span></p><p> </p><p><span > </span><span  >}</span></p><p> </p><p><span > </span><span  >static</span><span > </span><span  >String</span><span > convertToHexString</span><span  >(</span><span  >byte</span><span > data</span><span  >[])</span><span > </span><span  >{</span></p><p><span > </span><span  >StringBuffer</span><span > strBuffer </span><span  >=</span><span > </span><span  >new</span><span > </span><span  >StringBuffer</span><span  >();</span></p><p><span > </span><span  >for</span><span > </span><span  >(</span><span  >int</span><span > i </span><span  >=</span><span > </span><span  >0</span><span  >;</span><span > i </span><span  ><</span><span > data</span><span  >.</span><span >length</span><span  >;</span><span > i</span><span  >++)</span><span > </span><span  >{</span></p><p><span > </span><span >strBuffer</span><span  >.</span><span >append</span><span  >(</span><span  >Integer</span><span  >.</span><span >toHexString</span><span  >(</span><span  >0xff</span><span > </span><span  >&</span><span > data</span><span  >[</span><span >i</span><span  >]));</span></p><p><span > </span><span  >}</span></p><p><span > </span><span  >return</span><span > strBuffer</span><span  >.</span><span >toString</span><span  >();</span></p><p><span > </span><span  >}</span></p><p><span  >}</span></p>

★运行结果
<p ><span  >900150983cd24fb0d6963f7d28e17f72</span></p>

3.3、示例二 在这里我们将对计算生成的md5使用
sun.misc.BASE64Encoder进行简单的加密。
<p><span >  </span><span  >public</span><span > </span><span  >String</span><span > md5sumWithEncoder</span><span  >(</span><span  >String</span><span > text</span><span  >)</span><span > </span><span  >throws</span><span > </span><span  >NoSuchAlgorithmException</span><span  >,</span><span ></span></p><p><span  >UnsupportedEncodingException</span><span  >{</span></p><p><span >    </span><span  >/*确定计算方法*/</span></p><p><span >    </span><span  >MessageDigest</span><span > md5</span><span  >=</span><span  >MessageDigest</span><span  >.</span><span >getInstance</span><span  >(</span><span  >"MD5"</span><span  >);</span></p><p><span >    BASE64Encoder base64en </span><span  >=</span><span > </span><span  >new</span><span > BASE64Encoder</span><span  >();</span></p><p><span >    </span><span  >/*加密后的散列码字符串*/</span></p><p><span >    </span><span  >String</span><span > strMd5</span><span  >=</span><span >base64en</span><span  >.</span><span >encode</span><span  >(</span><span >md5</span><span  >.</span><span >digest</span><span  >(</span><span >text</span><span  >.</span><span >getBytes</span><span  >(</span><span  >"utf-8"</span><span  >)));</span></p><p><span >    </span><span  >return</span><span > strMd5</span><span  >;</span></p><p><span >  </span><span  >}</span></p>

调用函数
<p><span  >String</span><span > str</span><span  >=</span><span  >"0123456789"</span></p><p><span ></span><span  >System</span><span  >.</span><span  >out</span><span  >.</span><span >println</span><span  >(</span><span ><span  >md5sumWithEncoder</span></span><span  >(</span><span >str</span><span  >));</span></p>

输出
需要做网站?需要网络推广?欢迎咨询客户经理 13272073477