消息摘要算法包含MD(Message Digest,消息摘要算法)、SHA(Secure Hash Algorithm,安全散列算法)和MAC(Message Authentication Code,消息认证码算法)共3大系列,常用于验证数据的完整性,是数字签名算法的核心算法。
消息摘要算法又称为散列算法,其核心在于散列函数的单向性。即通过散列函数可获得对应的散列值,但不可通过该散列值反推原始信息。这是消息摘要算法的安全性的根本所在。
MD算法的使用
Sun中支持MD2和MD5算法,Bouncy Castle还支持MD4算法,Commons Codec的DigestUtils
是对Sun提供的MessageDigest
的一次封装,实现了MD5和SHA系列消息摘要算法的实现。
算法 | 摘要长度 | 备注 |
---|---|---|
MD2 | 128 | JAVA |
MD5 | 同上 | JAVA |
MD4 | ... | BC |
下面示例演示了MD5的处理。另外,对消息做MD5Hex处理后,得到的摘要值都是32位的十六进制字符串。
import org.apache.commons.codec.digest.DigestUtils;
public abstract class MD5Coder {
/**
* MD5加密
*
* @param data
* 待加密数据
* @return byte[] 消息摘要
*
* @throws Exception
*/
public static byte[] encodeMD5(String data) throws Exception {
// 执行消息摘要
return DigestUtils.md5(data);
}
/**
* MD5加密
*
* @param data
* 待加密数据
* @return byte[] 消息摘要
*
* @throws Exception
*/
public static String encodeMD5Hex(String data) throws Exception {
// 执行消息摘要
return DigestUtils.md5Hex(data);
}
}
用于校验文件的MD5值示例:
文件为 mysql-essential-5.1.38-win32.msi,存放于D盘根目录,MD5值为5a077abefee447cbb271e2aa7f6d5a47。
public class MD5Test {
/**
* 验证文件的MD5值
*
* @throws Exception
*/
@Test
public void testByMessageDigest() throws Exception {
// 文件路径
String path = "D:\\mysql-essential-5.1.38-win32.msi";
// 构建文件输入流
FileInputStream fis = new FileInputStream(new File(path));
// 初始化MessageDigest,并指定MD5算法
DigestInputStream dis = new DigestInputStream(fis, MessageDigest
.getInstance("MD5"));
// 流缓冲大小
int buf = 1024;
// 缓冲字节数组
byte[] buffer = new byte[buf];
// 当读到值大于-1就继续读
int read = dis.read(buffer, 0, buf);
while (read > -1) {
read = dis.read(buffer, 0, buf);
}
// 关闭流
dis.close();
// 获得MessageDigest
MessageDigest md = dis.getMessageDigest();
// 摘要处理
byte[] b = md.digest();
// 十六进制转换
String md5hex = Hex.encodeHexString(b);
// 验证
assertEquals(md5hex, "5a077abefee447cbb271e2aa7f6d5a47");
}
/**
* 验证文件的MD5值
*
* @throws Exception
*/
@Test
public void testByDigestUtils() throws Exception {
// 文件路径
String path = "D:\\mysql-essential-5.1.38-win32.msi";
// 构建文件输入流
FileInputStream fis = new FileInputStream(new File(path));
// 使用DigestUtils做MD5Hex处理
String md5hex = DigestUtils.md5Hex(fis);
// 关闭流
fis.close();
// 验证
assertEquals(md5hex, "5a077abefee447cbb271e2aa7f6d5a47");
}
}
SHA算法的使用
SHA算法,由美国国家安全局(NSA)设计,基于MD4算法基础演变而来,摘要的长度更长,安全性更高。
SHA家族共有SHA-1、SHA-224、SHA-256、SHA-384和SHA-512五种算法。Sun提供了SHA-1、SHA-256、SHA-384和SHA-512四种,且缺少对应的进制转换实现;Bouncy Castle提供了对SHA-224的支持;Commons Codec则是Sun的一个包装。后两者都支持多种形式的参数,支持十六进制字符串形式的摘要信息。
算法 | 摘要长度 | 备注 |
---|---|---|
SHA-1 | 160 | JAVA |
SHA-256 | 256 | JAVA |
SHA-384 | 384 | JAVA |
SHA-512 | 512 | JAVA |
SHA-224 | 224 | BC |
import java.security.MessageDigest;
import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import org.apache.commons.codec.digest.DigestUtils;
public abstract class SHACoder {
/**
* SHA加密
*
* @param data 待加密数据
* @return byte[] 消息摘要
* @throws Exception
*/
public static byte[] encodeSHA(String data) throws Exception {
// 执行消息摘要
return DigestUtils.sha(data);
}
/**
* SHAHex加密
*
* @param data 待加密数据
* @return String 消息摘要
* @throws Exception
*/
public static String encodeSHAHex(String data) throws Exception {
// 执行消息摘要
return DigestUtils.shaHex(data);
}
/**
* SHA-224加密
*
* @param data
* 待加密数据
* @return byte[] 消息摘要
*
* @throws Exception
*/
public static byte[] encodeSHA224(byte[] data) throws Exception {
// 加入BouncyCastleProvider支持
Security.addProvider(new BouncyCastleProvider());
// 初始化MessageDigest
MessageDigest md = MessageDigest.getInstance("SHA-224");
// 执行消息摘要
return md.digest(data);
}
/**
* SHA-224加密
*
* @param data
* 待加密数据
* @return byte[] 消息摘要
* @throws Exception
*/
public static String encodeSHA224Hex(byte[] data) throws Exception {
// 执行消息摘要
byte[] b = encodeSHA224(data);
// 做十六进制编码处理
return new String(Hex.encode(b));
}
/**
* SHA256加密
*
* @param data 待加密数据
* @return byte[