消息摘要算法---加密学习笔记(二)

介绍:

消息摘要算法分为三类

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

package com.timliu.security.message_digest;

import java.security.MessageDigest;
import java.security.Security;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.digests.MD2Digest;
import org.bouncycastle.crypto.digests.MD4Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class MD5Test {

	public static final String src = "hello world";

	public static void main(String[] args) {
		jdkMD5();
		jdkMD2();

		bcMD4();
		bcMD5();

		bc2jdkMD4();

		ccMD5();
		ccMD2();

	}

	// 用jdk实现:MD5
	public static void jdkMD5() {
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");// 得到MD5加密的对象
			byte[] md5Bytes = md.digest(src.getBytes());
			System.out.println("JDK MD5:" + Hex.encodeHexString(md5Bytes));// Hex.encodeHexString()将byte[]数组转换成十六进制
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 用jdk实现:MD2
	public static void jdkMD2() {
		try {
			MessageDigest md = MessageDigest.getInstance("MD2");
			byte[] md2Bytes = md.digest(src.getBytes());
			System.out.println("JDK MD2:" + Hex.encodeHexString(md2Bytes));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 用bouncy castle实现:MD5
	public static void bcMD5() {
		MD5Digest digest = new MD5Digest();
		digest.update(src.getBytes(), 0, src.getBytes().length);
		byte[] md5Bytes = new byte[digest.getDigestSize()];
		digest.doFinal(md5Bytes, 0);
		System.out.println("bouncy castle MD5:"
				+ org.bouncycastle.util.encoders.Hex.toHexString(md5Bytes));

	}

	// 用bouncy castle实现:MD4
	public static void bcMD4() {
		MD4Digest digest = new MD4Digest();
		digest.update(src.getBytes(), 0, src.getBytes().length);
		byte[] md4Bytes = new byte[digest.getDigestSize()];
		digest.doFinal(md4Bytes, 0);
		System.out.println("bouncy castle MD4:"
				+ org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
	}

	// 用bouncy castle与jdk结合实现:MD4
	public static void bc2jdkMD4() {
		try {
			Security.addProvider(new BouncyCastleProvider());
			MessageDigest md = MessageDigest.getInstance("MD4");
			byte[] md4Bytes = md.digest(src.getBytes());
			System.out.println("bc and JDK MD4:"
					+ Hex.encodeHexString(md4Bytes));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 用common codes实现实现:MD5
	public static void ccMD5() {
		System.out.println("common codes MD5:"
				+ DigestUtils.md5Hex(src.getBytes()));
	}

	// 用common codes实现实现:MD2
	public static void ccMD2() {
		System.out.println("common codes MD2:"
				+ DigestUtils.md2Hex(src.getBytes()));
	}

}
运行结果:



分析上边的代码:

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-256
256JDK
SHA-384384JDK
SHA-512512JDK

例子:

package com.timliu.security.message_digest;

import java.security.MessageDigest;
import java.security.Security;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.digests.SHA224Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class SHATest {
	public static final String src = "hello world";

	public static void main(String[] args) {
		jdkSHA1();
		bcSHA1();
		bcSHA224();
		bcSHA224b();
		ccSHA1();

	}

	// 用jdk实现:SHA1
	public static void jdkSHA1() {
		try {
			// SHA-1的名称就是SHA
			MessageDigest md = MessageDigest.getInstance("SHA");
			md.update(src.getBytes());
			System.out.println("jdk sha-1:" + Hex.encodeHexString(md.digest()));

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 用bouncy castle实现:SHA1
	public static void bcSHA1() {

		Digest digest = new SHA1Digest();
		digest.update(src.getBytes(), 0, src.getBytes().length);
		byte[] sha1Bytes = new byte[digest.getDigestSize()];
		digest.doFinal(sha1Bytes, 0);
		System.out.println("bc sha-1:"
				+ org.bouncycastle.util.encoders.Hex.toHexString(sha1Bytes));
	}

	// 用bouncy castle实现:SHA224
	public static void bcSHA224() {

		Digest digest = new SHA224Digest();
		digest.update(src.getBytes(), 0, src.getBytes().length);
		byte[] sha224Bytes = new byte[digest.getDigestSize()];
		digest.doFinal(sha224Bytes, 0);
		System.out.println("bc sha-224:"
				+ org.bouncycastle.util.encoders.Hex.toHexString(sha224Bytes));
	}

	// 用bouncy castle与jdk结合实现:SHA224
	public static void bcSHA224b() {

		try {
			Security.addProvider(new BouncyCastleProvider());
			MessageDigest md = MessageDigest.getInstance("SHA224");
			md.update(src.getBytes());
			System.out.println("bc and JDK sha-224:"
					+ Hex.encodeHexString(md.digest()));

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 用common codes实现实现:SHA1
	public static void ccSHA1() {
		//byte[]数组方式
		System.out.println("common codes SHA1 - 1 :"
				+ DigestUtils.sha1Hex(src.getBytes()));
		//String方式
		System.out
				.println("common codes SHA1 - 2 :" + DigestUtils.sha1Hex(src));
	}

}
运行结果:



分析上边的代码:

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
HmacMD4
128Bouncy Castle
HmacMD5
128JDK
HmacSHA1160JDK
HmacSHA224224Bouncy Castle
HmacSHA256
256JDK
HmacSHA384
384JDK
HmacSHA512
512JDK

例子:

package com.timliu.security.message_digest;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;

public class HMACTest {
	public static final String src = "hello world";

	public static void main(String[] args) {
		jdkHmacMD5();
		bcHmacMD5();

	}

	// 用jdk实现:
	public static void jdkHmacMD5() {
		try {
			// 初始化KeyGenerator
			KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
			// 产生密钥
			SecretKey secretKey = keyGenerator.generateKey();
			// 获取密钥
			// byte[] key = secretKey.getEncoded();
			byte[] key = Hex.decodeHex(new char[] { '1', '2', '3', '4', '5',
					'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e' });

			// 还原密钥,HmacMD5是算法的名字
			SecretKey restoreSecretKey = new SecretKeySpec(key, "HmacMD5");
			// 实例化MAC
			Mac mac = Mac.getInstance(restoreSecretKey.getAlgorithm());
			// 初始化MAC
			mac.init(restoreSecretKey);
			// 执行消息摘要
			byte[] hmacMD5Bytes = mac.doFinal(src.getBytes());
			System.out.println("jdk hmacMD5:"
					+ Hex.encodeHexString(hmacMD5Bytes));

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 用bouncy castle实现:
	public static void bcHmacMD5() {
		HMac hmac = new HMac(new MD5Digest());
		// 必须是16进制的字符,长度必须是2的倍数
		hmac.init(new KeyParameter(org.bouncycastle.util.encoders.Hex
				.decode("123456789abcde")));
		hmac.update(src.getBytes(), 0, src.getBytes().length);

		// 执行摘要
		byte[] hmacMD5Bytes = new byte[hmac.getMacSize()];
		hmac.doFinal(hmacMD5Bytes, 0);
		System.out.println("bc hmacMD5:"
				+ org.bouncycastle.util.encoders.Hex.toHexString(hmacMD5Bytes));

	}

}

运行结果:


代码分析:

使用jdk实现的方式中:

// 获取密钥
// byte[] key = secretKey.getEncoded();
byte[] key = Hex.decodeHex(new char[] { '1', '2', '3', '4', '5',
					'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e' });
这里的第一个是getEncoded()是自己生成的。 Hex.decodeHex()可以自己设定密钥的来源。


用bouncy castle实现的方式中:

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

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


HMAC算法的应用:

























版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值