消息摘要算法的主要特征是加密过程不须要密钥,而且通过加密的数据没法被解密,只有输入相同的明文数据通过相同的消息摘要算法才能获得相同的密文.java
所以能够对数据传输先后进行两次消息摘要,相同的内容摘要必定相同.通常地,把对一个信息的摘要称为该消息的指纹或数字签名。数字签名是保证信息的完整性和不能否认性的方法。算法
常见的消息摘要算法有:数据库
hash 算法:(一般也称散列算法,是一种将任意长度的消息变成固定长度的消息摘要算法,不可逆)apache
Message Digest Algorithm 5,流行度极高,但目前被发现存在碰撞冲突风险; 数组
任意长度输出为128bit=16字节摘要安全
SHA 指Security Hash Algorithm,由美国国家安全局NSA设计的安全散列算法系列; ide
SHA1 输出长度为160bit=20字节摘要编码
继SHA1 出现的算法(属于SHA-2类),安全性较SHA1更高; 加密
SHA256 输出长度为256bit=32字节摘要spa
MAC 算法
Message Authentication Code,消息认证码算法,基于HASH算法之上,增长了密钥的支持以提升安全性。
具体算法包括HmacMD5/HmacSHA1/HmacSHA256等,输入包括数据及密钥,输出长度与HASH算法一致。
密钥能够是任意长度的数据
MessageDigest 类是一个引擎类,它是为了提供诸如 SHA1 或 MD5 等密码上安全的报文摘要功能而设计的.
大体的主要步骤
1.获取MessageDigest对象
public static MessageDigest getInstance(String algorithm)//注意:算法名不区分大小写。
2.更新报文摘要对象
计算数据的摘要的第二步是向已初始化的报文摘要对象提供数据。这将经过一次或屡次调用如下某个 update(更新)方法来完成:
public void update(byte input) public void update(byte[] input) public void update(byte[] input, int offset, int len)3.计算摘要
经过调用 update 方法提供数据后,程序就调用如下某个 digest(摘要)方法来计算摘要:
public byte[] digest() public byte[] digest(byte[] input) public int digest(byte[] buf, int offset, int len)编码实现:
须要导入的依赖:
<dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.5</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.54</version> </dependency>
package com.fitc.soldier.service.common; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Security; import org.apache.commons.codec.binary.Hex; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.MD4Digest; import org.bouncycastle.crypto.digests.MD5Digest; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class MDdemo { private static final String CONTENT="惟梦想与好姑娘不可辜负"; public static void main(String[] args) throws NoSuchAlgorithmException { jdkMD5(CONTENT); jdkMD2(CONTENT); bcMD4(CONTENT); } /** * JDK 提供的MD5实现 * 做为主要的应用 * */ public static void jdkMD5(String Content) { try { //注意:算法名不区分大小写。例如,如下全部调用都是相等的: MessageDigest messageDigest = MessageDigest.getInstance("MD5"); // 使用MD5算法对消息摘要(使用digest(byte[])的重载方法update 初始化原始数据) byte[] digest = messageDigest.digest(Content.getBytes()); // 为了使摘要的结果以String 方式打印 便于对比 String encodeHexString = Hex.encodeHexString(digest); System.out.println("JDK 的MD5 摘要算法:" + encodeHexString); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } /** * JDK 提供的MD2实现 * */ public static void jdkMD2(String Content) { try { MessageDigest messageDigest = MessageDigest.getInstance("MD2"); // 使用MD5算法对消息摘要 byte[] digest = messageDigest.digest(Content.getBytes()); // 为了使摘要的结果以String 方式打印 便于对比 String encodeHexString = Hex.encodeHexString(digest); System.out.println("JDK 的MD2 摘要算法:" + encodeHexString); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } /** * bc支持的MD4 * @throws NoSuchAlgorithmException */ public static void bcMD4(String Content) throws NoSuchAlgorithmException { // Security.addProvider(new BouncyCastleProvider()); // MessageDigest digest=MessageDigest.getInstance("MD4"); // byte[] digest2 = digest.digest(Content.getBytes()); // System.out.println(" bcMD4摘要算法:" + Hex.encodeHexString(digest2)); Digest digest=new MD4Digest(); // 初始化 digest.update(Content.getBytes(), 0, Content.getBytes().length); int digestSize = digest.getDigestSize(); // 定义摘要后的二进制数据 接收数组 byte[] md4Byte=new byte[digestSize]; // 对消息进行摘要 第二个参数 插入数据的偏移量 即从什么位置插入 digest.doFinal(md4Byte, 0); System.out.println(" bcMD4摘要算法:" + Hex.encodeHexString(md4Byte)); } }
MD算法的应用场景:
对于用户的密码数据,在持久化时使用明文存储不符合安全性的要求,此时能够对密码进行摘要算法而后再进行持久化.在此引用慕课网的教程图片:
在注册时存入数据库的是密码的摘要,在登录时对登陆的密码进行摘要而后对比数据库中存储的摘要判断是否登陆成功.
/** * JDK 提供的SHA1等实现 * 做为主要的应用 * */ public static void jdkSHA1(String Content) { try { //SHA-1 ,SHA-224,SHA-256 .... MessageDigest messageDigest = MessageDigest.getInstance("SHA-1"); //初始化参数数据 messageDigest.update(Content.getBytes());; // 使用SHA1算法对消息摘要 byte[] digest = messageDigest.digest(); // 为了使摘要的结果以String 方式打印 便于对比 String encodeHexString = Hex.encodeHexString(digest); System.out.println("JDK 的SHA1 摘要算法:" + encodeHexString); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } }
对于其余SHA算法大同小异,在此再也不赘叙.
MAC(也成HMAC)算法与MD以及SHA算法相比,在兼容两种算法的基础上加入了密钥.
在使用密钥时,须要了解几个类:
keyGenerator:秘钥生成器,也就是更具算法类型随机生成一个秘钥,例如HMAC,因此这个大部分用在非可逆的算法中.
KeyPairGenerator:秘钥对生成器,也就是能够生成一对秘钥,也就是公钥和私钥,因此大部分使用在非对称加密中
public static void hmac(String content) throws NoSuchAlgorithmException, InvalidKeyException{ /* * 根据算法名称获取密钥生成器 */ KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacMD5"); //生成密钥 SecretKey generateKey = keyGenerator.generateKey(); //还原密钥 // SecretKey restoregenerateKey=new SecretKeySpec(generateKey.getEncoded(), "HmacMD5"); /** * 建立Mac对象 */ Mac mac=Mac.getInstance(generateKey.getAlgorithm()); /** * 初始化 */ mac.init(generateKey); byte[] doFinal = mac.doFinal(content.getBytes()); System.out.println("HmacMD5 :"+Hex.encodeHexString(doFinal)); }
应用场景假设:
甲乙双方进行数据交换能够采起以下流程完成
一、甲方向乙方公布摘要算法(就是指定要使用的摘要算法名)
二、甲乙双方按照约定构造密钥,双方拥有相同的密钥(通常是一方构造密钥后通知另一方,此过程不须要经过程序实现,就是双方约定个字符串,可是这个字符串可不是随便设定的,也是经过相关算法获取的)
三、甲方使用密钥对消息作摘要处理,而后将消息和生成的摘要消息一同发送给乙方
四、乙方收到消息后,使用甲方已经公布的摘要算法+约定好的密钥 对收到的消息进行摘要处理。而后比对本身的摘要消息和甲方发过来的摘要消息。甄别消息是不是甲方发送过来的