三种摘要算法的简单介绍

原文地址:

http://blog.csdn.net/u013991521/article/details/48193953

介绍:

消息摘要算法分为三类:

MD(Message Digest):消息摘要

SHA(Secure Hash Algorithm):安全散列

MAC(Message Authentication Code):消息认证码

 

这三类算法的主要作用:验证数据的完整性

消息摘要算法是有关于数字签名的核心算法。

 

MD算法:

MD算法家族:

生成的消息摘要都是128位的。

包括:MD2,MD4,MD5

从安全性上说:MD5 > MD4 > MD2

应用举例

电驴(点对点的下载工具)使用的是经过改良的MD4的算法,这种改良后的MD4算法主要是用于通过P2P下载的文件截成块,分块之后进行摘要,通过摘要来验证所文件的最终的完整性,如果不完整是解压不开的。

 

算法摘要长度实现方
MD2128JDK
MD4128Bouncy Castle
MD5128JDK

 

 

 

[java]  view plain  copy
 
  1. package com.timliu.security.message_digest;  
  2.   
  3. import java.security.MessageDigest;  
  4. import java.security.Security;  
  5.   
  6. import org.apache.commons.codec.binary.Hex;  
  7. import org.apache.commons.codec.digest.DigestUtils;  
  8. import org.bouncycastle.crypto.digests.MD2Digest;  
  9. import org.bouncycastle.crypto.digests.MD4Digest;  
  10. import org.bouncycastle.crypto.digests.MD5Digest;  
  11. import org.bouncycastle.jce.provider.BouncyCastleProvider;  
  12.   
  13. public class MD5Test {  
  14.   
  15.     public static final String src = "hello world";  
  16.   
  17.     public static void main(String[] args) {  
  18.         jdkMD5();  
  19.         jdkMD2();  
  20.   
  21.         bcMD4();  
  22.         bcMD5();  
  23.   
  24.         bc2jdkMD4();  
  25.   
  26.         ccMD5();  
  27.         ccMD2();  
  28.   
  29.     }  
  30.   
  31.     // 用jdk实现:MD5  
  32.     public static void jdkMD5() {  
  33.         try {  
  34.             MessageDigest md = MessageDigest.getInstance("MD5");// 得到MD5加密的对象  
  35.             byte[] md5Bytes = md.digest(src.getBytes());  
  36.             System.out.println("JDK MD5:" + Hex.encodeHexString(md5Bytes));// Hex.encodeHexString()将byte[]数组转换成十六进制  
  37.         } catch (Exception e) {  
  38.             e.printStackTrace();  
  39.         }  
  40.     }  
  41.   
  42.     // 用jdk实现:MD2  
  43.     public static void jdkMD2() {  
  44.         try {  
  45.             MessageDigest md = MessageDigest.getInstance("MD2");  
  46.             byte[] md2Bytes = md.digest(src.getBytes());  
  47.             System.out.println("JDK MD2:" + Hex.encodeHexString(md2Bytes));  
  48.         } catch (Exception e) {  
  49.             e.printStackTrace();  
  50.         }  
  51.     }  
  52.   
  53.     // 用bouncy castle实现:MD5  
  54.     public static void bcMD5() {  
  55.         MD5Digest digest = new MD5Digest();  
  56.         digest.update(src.getBytes(), 0, src.getBytes().length);  
  57.         byte[] md5Bytes = new byte[digest.getDigestSize()];  
  58.         digest.doFinal(md5Bytes, 0);  
  59.         System.out.println("bouncy castle MD5:"  
  60.                 + org.bouncycastle.util.encoders.Hex.toHexString(md5Bytes));  
  61.   
  62.     }  
  63.   
  64.     // 用bouncy castle实现:MD4  
  65.     public static void bcMD4() {  
  66.         MD4Digest digest = new MD4Digest();  
  67.         digest.update(src.getBytes(), 0, src.getBytes().length);  
  68.         byte[] md4Bytes = new byte[digest.getDigestSize()];  
  69.         digest.doFinal(md4Bytes, 0);  
  70.         System.out.println("bouncy castle MD4:"  
  71.                 + org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));  
  72.     }  
  73.   
  74.     // 用bouncy castle与jdk结合实现:MD4  
  75.     public static void bc2jdkMD4() {  
  76.         try {  
  77.             Security.addProvider(new BouncyCastleProvider());  
  78.             MessageDigest md = MessageDigest.getInstance("MD4");  
  79.             byte[] md4Bytes = md.digest(src.getBytes());  
  80.             System.out.println("bc and JDK MD4:"  
  81.                     + Hex.encodeHexString(md4Bytes));  
  82.         } catch (Exception e) {  
  83.             e.printStackTrace();  
  84.         }  
  85.     }  
  86.   
  87.     // 用common codes实现实现:MD5  
  88.     public static void ccMD5() {  
  89.         System.out.println("common codes MD5:"  
  90.                 + DigestUtils.md5Hex(src.getBytes()));  
  91.     }  
  92.   
  93.     // 用common codes实现实现:MD2  
  94.     public static void ccMD2() {  
  95.         System.out.println("common codes MD2:"  
  96.                 + DigestUtils.md2Hex(src.getBytes()));  
  97.     }  
  98.   
  99. }  

运行结果:

 

 

分析上边的代码:

bouncy castle提供了MD4,MD5,MD2的实现

common codes只是对JDK中MD5,MD2的实现进行了简化

JDK提供的MD5,MD2的实现偏底层一些,缺少了相应的进制的转换。比如,将byte[]数组转换为十六进制

 

MD5算法的应用:

上边是简单的用户注册,登录一个系统的过程分析图。

注册时,系统会将用户的密码进行消息摘要(如MD5),然后将用户名和密码保存到数据库中。

登录时,系统会将用户输入的密码进行消息摘要(如MD5),然后将输入的用户名和加密后的密码与数据库中的进行比对,判断是否正确。

 

SHA算法:

介绍:

安全散列算法

固定长度摘要信息

包括:SHA-1,SHA-2(SHA-224,SHA-256,SHA-384,SHA-512)

 

算法摘要长度实现方
SHA-1160JDK
SHA-224224Bouncy Castle
SHA-256256JDK
SHA-384384JDK
SHA-512512JDK


例子:

 

 

[java]  view plain  copy
 
  1. package com.timliu.security.message_digest;  
  2.   
  3. import java.security.MessageDigest;  
  4. import java.security.Security;  
  5.   
  6. import org.apache.commons.codec.binary.Hex;  
  7. import org.apache.commons.codec.digest.DigestUtils;  
  8. import org.bouncycastle.crypto.Digest;  
  9. import org.bouncycastle.crypto.digests.SHA1Digest;  
  10. import org.bouncycastle.crypto.digests.SHA224Digest;  
  11. import org.bouncycastle.jce.provider.BouncyCastleProvider;  
  12.   
  13. public class SHATest {  
  14.     public static final String src = "hello world";  
  15.   
  16.     public static void main(String[] args) {  
  17.         jdkSHA1();  
  18.         bcSHA1();  
  19.         bcSHA224();  
  20.         bcSHA224b();  
  21.         ccSHA1();  
  22.   
  23.     }  
  24.   
  25.     // 用jdk实现:SHA1  
  26.     public static void jdkSHA1() {  
  27.         try {  
  28.             // SHA-1的名称就是SHA  
  29.             MessageDigest md = MessageDigest.getInstance("SHA");  
  30.             md.update(src.getBytes());  
  31.             System.out.println("jdk sha-1:" + Hex.encodeHexString(md.digest()));  
  32.   
  33.         } catch (Exception e) {  
  34.             e.printStackTrace();  
  35.         }  
  36.     }  
  37.   
  38.     // 用bouncy castle实现:SHA1  
  39.     public static void bcSHA1() {  
  40.   
  41.         Digest digest = new SHA1Digest();  
  42.         digest.update(src.getBytes(), 0, src.getBytes().length);  
  43.         byte[] sha1Bytes = new byte[digest.getDigestSize()];  
  44.         digest.doFinal(sha1Bytes, 0);  
  45.         System.out.println("bc sha-1:"  
  46.                 + org.bouncycastle.util.encoders.Hex.toHexString(sha1Bytes));  
  47.     }  
  48.   
  49.     // 用bouncy castle实现:SHA224  
  50.     public static void bcSHA224() {  
  51.   
  52.         Digest digest = new SHA224Digest();  
  53.         digest.update(src.getBytes(), 0, src.getBytes().length);  
  54.         byte[] sha224Bytes = new byte[digest.getDigestSize()];  
  55.         digest.doFinal(sha224Bytes, 0);  
  56.         System.out.println("bc sha-224:"  
  57.                 + org.bouncycastle.util.encoders.Hex.toHexString(sha224Bytes));  
  58.     }  
  59.   
  60.     // 用bouncy castle与jdk结合实现:SHA224  
  61.     public static void bcSHA224b() {  
  62.   
  63.         try {  
  64.             Security.addProvider(new BouncyCastleProvider());  
  65.             MessageDigest md = MessageDigest.getInstance("SHA224");  
  66.             md.update(src.getBytes());  
  67.             System.out.println("bc and JDK sha-224:"  
  68.                     + Hex.encodeHexString(md.digest()));  
  69.   
  70.         } catch (Exception e) {  
  71.             e.printStackTrace();  
  72.         }  
  73.     }  
  74.   
  75.     // 用common codes实现实现:SHA1  
  76.     public static void ccSHA1() {  
  77.         //byte[]数组方式  
  78.         System.out.println("common codes SHA1 - 1 :"  
  79.                 + DigestUtils.sha1Hex(src.getBytes()));  
  80.         //String方式  
  81.         System.out  
  82.                 .println("common codes SHA1 - 2 :" + DigestUtils.sha1Hex(src));  
  83.     }  
  84.   
  85. }  

运行结果:

 


 

分析上边的代码:

bouncy castle提供了所有的SHA消息摘要算法,其中SHA-224消息摘要算法是JDK中没有提供的。

common codes只是对JDK提供的SHA消息摘要算法进行了简化。

 

SHA算法的应用

分析上图:

第三步和第四步是发送方将已经对消息进行SHA算法处理的消息摘要和原始的消息发送给接收方,接收方对消息进行鉴别。

消息鉴别是指接收方将原始信息进行摘要,然后与接收到的摘要信息进行比对,判断接收方接收到的消息是否是发送方发送的最原始的消息。

 

比如QQ的联合登陆,就是使用QQ号码登陆其他的网站需要这些过程(但是这个例子不局限与SHA算法加密):

1.在消息内容中加入约定的Key(QQ会给接入方一个Key)

2.增加时间戳(QQ会约定一个消息传递的格式)

3.排序(对消息按照一定的格式进行排序(如:msg:原始消息+key+时间戳),然后对消息进行算法摘要)

4.将摘要后的信息发送给接收方

5.接收方再按照上面的规则进行操作

http://**?msg=12Hsad74mj&timestamp=1309488734

msg是经过加密的摘要消息

timestamp是时间戳

 

MAC算法

介绍:

HMAC(keyed-Hash Message Authentication Code):含有密钥的散列函数算法

包含了MD和SHA两个系列的消息摘要算法

HMAC只是在原有的MD和SHA算法的基础上添加了密钥。

融合了MD,SHA:

MD系列:HmacMD2,HmacMD4,HmacMD5

SHA系列:HmacSHA1,HmacSHA224,HmacSHA256,HmacSHA38

,HmacSHA512

 

 

算法摘要长度实现方
HmacMD2128Bouncy Castle
HmacMD4128Bouncy Castle
HmacMD5128JDK
HmacSHA1160JDK
HmacSHA224224Bouncy Castle
HmacSHA256256JDK
HmacSHA384384JDK
HmacSHA512512JDK

 

 

 

例子:

 

[java]  view plain  copy
 
  1. package com.timliu.security.message_digest;  
  2.   
  3. import javax.crypto.KeyGenerator;  
  4. import javax.crypto.Mac;  
  5. import javax.crypto.SecretKey;  
  6. import javax.crypto.spec.SecretKeySpec;  
  7.   
  8. import org.apache.commons.codec.binary.Hex;  
  9. import org.bouncycastle.crypto.digests.MD5Digest;  
  10. import org.bouncycastle.crypto.macs.HMac;  
  11. import org.bouncycastle.crypto.params.KeyParameter;  
  12.   
  13. public class HMACTest {  
  14.     public static final String src = "hello world";  
  15.   
  16.     public static void main(String[] args) {  
  17.         jdkHmacMD5();  
  18.         bcHmacMD5();  
  19.   
  20.     }  
  21.   
  22.     // 用jdk实现:  
  23.     public static void jdkHmacMD5() {  
  24.         try {  
  25.             // 初始化KeyGenerator  
  26.             KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");  
  27.             // 产生密钥  
  28.             SecretKey secretKey = keyGenerator.generateKey();  
  29.             // 获取密钥  
  30.             // byte[] key = secretKey.getEncoded();  
  31.             byte[] key = Hex.decodeHex(new char[] { '1''2''3''4''5',  
  32.                     '6''7''8''9''a''b''c''d''e' });  
  33.   
  34.             // 还原密钥,HmacMD5是算法的名字  
  35.             SecretKey restoreSecretKey = new SecretKeySpec(key, "HmacMD5");  
  36.             // 实例化MAC  
  37.             Mac mac = Mac.getInstance(restoreSecretKey.getAlgorithm());  
  38.             // 初始化MAC  
  39.             mac.init(restoreSecretKey);  
  40.             // 执行消息摘要  
  41.             byte[] hmacMD5Bytes = mac.doFinal(src.getBytes());  
  42.             System.out.println("jdk hmacMD5:"  
  43.                     + Hex.encodeHexString(hmacMD5Bytes));  
  44.   
  45.         } catch (Exception e) {  
  46.             e.printStackTrace();  
  47.         }  
  48.     }  
  49.   
  50.     // 用bouncy castle实现:  
  51.     public static void bcHmacMD5() {  
  52.         HMac hmac = new HMac(new MD5Digest());  
  53.         // 必须是16进制的字符,长度必须是2的倍数  
  54.         hmac.init(new KeyParameter(org.bouncycastle.util.encoders.Hex  
  55.                 .decode("123456789abcde")));  
  56.         hmac.update(src.getBytes(), 0, src.getBytes().length);  
  57.   
  58.         // 执行摘要  
  59.         byte[] hmacMD5Bytes = new byte[hmac.getMacSize()];  
  60.         hmac.doFinal(hmacMD5Bytes, 0);  
  61.         System.out.println("bc hmacMD5:"  
  62.                 + org.bouncycastle.util.encoders.Hex.toHexString(hmacMD5Bytes));  
  63.   
  64.     }  
  65.   
  66. }  


运行结果:

 

代码分析:

使用jdk实现的方式中:

 

[java]  view plain  copy
 
  1. // 获取密钥  
  2. // byte[] key = secretKey.getEncoded();  
  3. byte[] key = Hex.decodeHex(new char[] { '1''2''3''4''5',  
  4.                     '6''7''8''9''a''b''c''d''e' });  

这里的第一个是getEncoded()是自己生成的。Hex.decodeHex()可以自己设定密钥的来源。

 

 

用bouncy castle实现的方式中:

 

[java]  view plain  copy
 
  1. // 必须是16进制的字符,长度必须是2的倍数  
  2.         hmac.init(new KeyParameter(org.bouncycastle.util.encoders.Hex  
  3.                 .decode("123456789abcde")));  


这里的Hex.decode()也是自己设定的密钥的来源。注意:来源必须是16进制的字符,长度必须是2的倍数。

 

 

HMAC算法的应用:

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值