MessageDigest简单介绍

摘要:
关于信息摘要和散列码请參照《数字证书简单介绍》MessageDigest通过其getInstance系列静态函数来进行实例化和初始化。MessageDigest对象通过使用update方法处理数据。digest方法被调用后,MessageDigest对象被又一次设置成其初始状态。MessageDigest的实现可任意选择是否实现Cloneable接口。注意2:因为历史原因,此类是抽象的,是从MessageDigestSpi扩展的。注意3:MessageDigest并非单实例的。

本文博客原文

參考文章:http://blog.sina.com.cn/s/blog_4f36423201000c1e.html
一、概述
java.security.MessageDigest类用于为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。简单点说就是用于生成散列码信息摘要是安全的单向哈希函数,它接收随意大小的数据,输出固定长度的哈希值。关于信息摘要散列码请參照《数字证书简单介绍

MessageDigest通过其getInstance系列静态函数来进行实例化和初始化。MessageDigest 对象通过使用update方法处理数据。不论什么时候都能够调用reset方法重置摘要。一旦全部须要更新的数据都已经被更新了,应该调用digest方法之中的一个完毕哈希计算并返回结果。

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

MessageDigest的实现可任意选择是否实现 Cloneable 接口。client应用程能够通过尝试复制和捕获 CloneNotSupportedException 測试可复制性:

MessageDigestmd =MessageDigest.getInstance("SHA");

try{

md.update(toChapter1);

MessageDigesttc1 =md.clone();

byte[]toChapter1Digest =tc1.digest();

md.update(toChapter2);

...etc.

}catch(CloneNotSupportedExceptioncnse){

thrownewDigestException("couldn't make digest of partial content");

}

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

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

注意3MessageDigest并非单实例的。例如以下代码所看到的:

try

{

MessageDigestmdTemp1 =MessageDigest.getInstance("MD5");

MessageDigestmdTemp2=MessageDigest.getInstance("MD5");

MessageDigestmdTemp3=MessageDigest.getInstance("MD5");

System.out.println("mdTemp1==mdTemp2?:"+(mdTemp1==mdTemp2));

System.out.println("mdTemp2==mdTemp3?:"+(mdTemp2==mdTemp3));

}catch(NoSuchAlgorithmExceptione)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

执行结果

mdTemp1==mdTemp2?:false

mdTemp2==mdTemp3?:false

构造方法摘要
protectedMessageDigest(Stringalgorithm)
创建具有指定算法名称的MessageDigest实例对象
方法摘要
Objectclone()
假设实现是可复制的,则返回一个副本。
byte[]digest()
通过运行诸如填充之类的终于操作完毕哈希计算。
byte[]digest(byte[]input)
使用指定的字节数组对摘要进行最后更新,然后完毕摘要计算。
intdigest(byte[]buf, intoffset, intlen)
通过运行诸如填充之类的终于操作完毕哈希计算。
StringgetAlgorithm()
返回标识算法的独立于实现细节的字符串。
intgetDigestLength()
返回以字节为单位的摘要长度,假设提供程序不支持此操作而且实现是不可复制的,则返回 0。
staticMessageDigestgetInstance(Stringalgorithm)
生成实现指定摘要算法的 MessageDigest 对象。
staticMessageDigestgetInstance(Stringalgorithm,Providerprovider)
生成实现指定提供程序提供的指定算法的 MessageDigest 对象,假设该算法可从指定的提供程序得到的话。
staticMessageDigestgetInstance(Stringalgorithm,Stringprovider)
生成实现指定提供程序提供的指定算法的 MessageDigest 对象,假设该算法可从指定的提供程序得到的话。
ProvidergetProvider()
返回此信息摘要对象的提供程序。
staticbooleanisEqual(byte[]digesta, byte[]digestb)
比較两个摘要的相等性。
voidreset()
重置摘要以供再次使用。
StringtoString()
返回此信息摘要对象的字符串表示形式。
voidupdate(byteinput)
使用指定的字节更新摘要。
voidupdate(byte[]input)
使用指定的字节数组更新摘要。
voidupdate(byte[]input, intoffset, intlen)
使用指定的字节数组,从指定的偏移量開始更新摘要。
voidupdate(ByteBufferinput)
使用指定的 ByteBuffer 更新摘要。
二、实际实践
2.1、创建MessageDigest对象
计算信息摘(即散列码)要做的第一步是创建MessageDigest对象实例。像全部的引擎类一样,获取某类报文摘要算法(即散列算法,比方MD5)的MessageDigest对象的途径是调用MessageDigest类中的getInstance静态factory方法:

publicstaticMessageDigestgetInstance(Stringalgorithm)

注意:算法名不区分大写和小写。比如,下面全部调用都是相等的:
MessageDigest.getInstance("SHA");
MessageDigest.getInstance("sha");
MessageDigest.getInstance("sHa");
调用程序可选择指定提供者名称,以保证所要求的算法是由已命名提供者实现的:

publicstaticMessageDigestgetInstance(Stringalgorithm,Stringprovider);

调用 getInstance 将返回已初始化过的MessageDigest对象。因此,它不须要进一步的初始化。
2.2、向MessageDigest传送要计算的数据
计算数据的摘要的第二步是向已初始化的MessageDigest对象提供传送要计算的数据。这将通过一次或多次调用下面某个update(更新)方法来完毕:
publicvoidupdate(byteinput);
publicvoidupdate(byte[]input);
publicvoidupdate(byte[]input,intoffset,intlen);
2.3、计算摘要
通过调用 update 方法向MessageDigest对象传送要计算的数据后,你就能够调用下面某个 digest(摘要)方法来计算摘要(即生成散列码):
publicbyte[]digest();
publicbyte[]digest(byte[]input);
publicintdigest(byte[]buf,intoffset,intlen);
前两个方法返回计算出的摘要。后一个方法把计算出的摘要储存在所提供的 buf 缓冲区中,起点是 offset。len 是 buf 中分配给该摘要的字节数。该方法返回实际存储在 buf 中的字节数。
对第二个接受输入字节数组变量的 digest 方法的调用等价于用指定的输入调用:

publicvoidupdate(byte[]input)

,接着调用不带參数的 digest 方法.
三、样例演示
3.1、★ 编程思路:
java.security包中的MessageDigest类提供了计算消息摘要即生成散列码的方法,首先生成对象,运行其update( )方法可
以将原始数据传递给该对象,然后运行其digest( )方法就可以得到消息摘要。详细过程例如以下:
(1)生成MessageDigest对象

MessageDigestm=MessageDigest.getInstance("MD5");

MessageDigest类也是一个工厂类,其构造器是受保护的,不同意
直接使用new MessageDigist( )来创建对象,而必须通过其静态方法getInstance( )生成MessageDigest对象
当中传入的參数指定计算消息摘要所使用的算法,经常使用的有"MD5","SHA"等。
(2)传入须要计算的字符串

m.update(x.getBytes("UTF8"));

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

bytes[]=m.digest();

分析:运行MessageDigest对象的digest( )方法完毕计算,计算的结果通过字节类型的数组返回。
(4)处理计算结果
必要的话能够使用例如以下代码将计算结果(byte数组)转换为字符串。
staticStringconvertToHexString(bytedata[]){
StringBufferstrBuffer =newStringBuffer();
for(inti =0;i <data.length;i++){
strBuffer.append(Integer.toHexString(0xff&data[i]));
}
returnstrBuffer.toString();
}
3.2、演示样例一
完整程序例如以下:
publicclassMessageDigestDemoextendsThread{
publicvoidrun(){
Stringtext ="abc";
bytedata[]=null;
MessageDigestm;
try{
data =text.getBytes("UTF8");
m =MessageDigest.getInstance("MD5");
m.update(data);
byteresultData[]=m.digest();
System.out.println(convertToHexString(resultData));
}catch(NoSuchAlgorithmExceptione){
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
staticStringconvertToHexString(bytedata[]){
StringBufferstrBuffer =newStringBuffer();
for(inti =0;i <data.length;i++){
strBuffer.append(Integer.toHexString(0xff&data[i]));
}
returnstrBuffer.toString();
}
}
★执行结果

900150983cd24fb0d6963f7d28e17f72

3.3、演示样例二
在这里我们将对计算生成的md5使用sun.misc.BASE64Encoder进行简单的加密。
publicStringmd5sumWithEncoder(Stringtext)throwsNoSuchAlgorithmException,
UnsupportedEncodingException{
/*确定计算方法*/
MessageDigestmd5=MessageDigest.getInstance("MD5");
BASE64Encoder base64en =newBASE64Encoder();
/*加密后的散列码字符串*/
StringstrMd5=base64en.encode(md5.digest(text.getBytes("utf-8")));
returnstrMd5;
}
调用函数
Stringstr="0123456789"
System.out.printlnmd5sumWithEncoderstr));
输出
eB5eJF1ptWaXm4bijSPyxw==
3.4、演示样例三
关于此请參考《一点关于计算MD5的封装

免责声明:文章转载自《MessageDigest简单介绍》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇awk命令学习(1)深度理解 原码, 反码, 补码下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

MySQL复合主键下ON DUPLICATE KEY UPDATE语句失效问题

问题的起因,假设有一张表,里面保存了交易订单,每张订单有唯一的ID,有最后更新时间,还有数据,详情如下: 1 2 3 4 5 6 7 +-------+----------+------+-----+---------------------+-------+ |Field|Type|Null|Key|Default|Extra| +--...

Ubuntu 16.04出现:Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /var/cache/app-info -a -e /usr/bin/appstreamcli; then appstreamcli refresh &amp;gt; /dev/null; fi'

错误: Reading package lists... Done E: Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /var/cache/app-info -a -e /usr/bin/appstreamcli; then apps...

Golang 对MongoDB的操作简单封装

使用MongoDB的Go驱动库mgo,对MongoDB的操作做一下简单封装 初始化 操作没有用户权限的MongoDB var globalS *mgo.Session func init() { s, err := mgo.Dial(dialInfo) if err != nil { log.Fatalf("Create...

SQL Server 触发器

SQL Server 触发器 触发器是一种特殊类型的存储过程,它不同于之前的我们介绍的存储过程。触发器主要是通过事件进行触发被自动调用执行的。而存储过程可以通过存储过程的名称被调用。 Ø 什么是触发器 触发器对表进行插入、更新、删除的时候会自动执行的特殊存储过程。触发器一般用在check约束更加复杂的约束上面。触发器和普通的存储过程的区别是:触发器是当对某...

svn的应用

SVN 如何来进行多人协作开发? 在实际工作中,通常是一个小组或者一个团队一起开发同一个项目,不同的人开发不同的功能模块,有一个公共的地方存放项目代码。 如果多个人同时对同一个文件做了修改,比如按照分工,两个人分别做文章模块的增删改查功能,需要操作同一个文件article控制器,如果大家同时完成工作并提交代码,会出现一个代码覆盖的问题。 解决办法: ①合理...

Docker Swarm 常用命令

# 管理配置文件 docker config     # 查看已创建配置文件     - docker config ls     # 将已有配置文件添加到docker配置文件中     - docker config create docker 配置文件名 本地配置文件  # 管理swarm节点 docker node     # 查看集群中的...