消息摘要
消息摘要(Message Digest)又称为数字摘要(Digital Digest)
它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生
使用数字摘要生成的值是不可以篡改的,为了保证文件或者值的安全
特点
无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。
只要输入的消息不同,对其进行摘要以后产生的摘要消息也必不相同;但相同的输入必会产生相同的输出
消息摘要是单向、不可逆的
例如应用MD5算法摘要的消息有128个比特位,用SHA-1算法摘要的消息最终有160比特位的输出
常见的加密方式
- MD5
- SHA1
- SHA256
- SHA512
详解加密方式
MD5加密
message-digest algorithm 5(简称MD5),信息-摘要算法
底层采用的是散列哈希算法, 对一段信息产生信息摘要,防止被篡改,不算是加密算法,而是摘要算法
无论是多长的输入,md5都会输出长度为128bits(16字节)的哈希值
代码案例:
package com.example.password_discipline.utils;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* MD5
*/
public class MD5 {
/**
* 获取MD5消息摘要
*
* @param data
* 源数据
* @return MD5消息摘要
*/
public static byte[] getMD5(byte[] data) {
byte[] md5 = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md5 = md.digest(data);
} catch (Exception e) {
}
return md5;
}
/*
* MD5字符串
*/
public static String getMD5Str(String str) {
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
if (!StringUtils.isEmpty(str)) {
messageDigest.update(str.getBytes("UTF-8"));
}
} catch (NoSuchAlgorithmException e) {
// logger.error(e);
} catch (UnsupportedEncodingException e) {
// logger.error(e);
}
byte[] byteArray = messageDigest.digest();
StringBuffer md5StrBuff = new StringBuffer();
for (int i = 0; i < byteArray.length; i++) {
if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
else
md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
}
return md5StrBuff.toString().toUpperCase();
}
/*
* MD5字符串
*/
public static String getMD5Str(String str, String charset) {
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
if (!StringUtils.isEmpty(str)) {
messageDigest.update(str.getBytes(charset));
}
} catch (NoSuchAlgorithmException e) {
} catch (UnsupportedEncodingException e) {
}
byte[] byteArray = messageDigest.digest();
StringBuffer md5StrBuff = new StringBuffer();
for (int i = 0; i < byteArray.length; i++) {
if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
else
md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
}
return md5StrBuff.toString().toUpperCase();
}
/**
* 16位MD5方法
* @param sourceStr
* @return
*/
public static String MD5_16(String sourceStr) {
String result = "";
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(sourceStr.getBytes());
byte b[] = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
result = buf.toString().substring(8, 24);
} catch (NoSuchAlgorithmException e) {
}
return result;
}
/*
* MD5字符串
*/
public static String getMD5Str(byte[] data) {
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
messageDigest.update(data);
} catch (NoSuchAlgorithmException e) {
}
byte[] byteArray = messageDigest.digest();
StringBuffer md5StrBuff = new StringBuffer();
for (int i = 0; i < byteArray.length; i++) {
if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
else
md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
}
return md5StrBuff.toString().toUpperCase();
}
public static void main(String[] args){
System.out.println(MD5.getMD5Str("123456"));
}
}
SHA1算法 SHA256算法 SHA512算法
SHA1是一种密码散列函数,由美国国家安全局设计,主要适用于数字签名标准里面定义的数字签名算法。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。今天我们将讨论的是SHA1算法原理和流程。
入门代码,只需要将MD5换成SHA1
package com.example.password_discipline.digest;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.security.MessageDigest;
public class DigestHexDemo {
public static void main(String[] args) throws Exception {
String data = "aa";
String algorithm = "MD5";
DigestHexDemo.getDigest(data, algorithm);
String sha1 = getDigest(data, "SHA-1");
String sha256 = getDigest(data, "SHA-256");
String sha512 = getDigest(data, "SHA-512");
}
public static String toHex(byte[] digest){
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
String temp = Integer.toHexString(b & 0xff);
if(temp.length() == 1){
sb.append("0" + temp);
}else {
sb.append(temp);
}
}
return sb.toString();
}
/**
* 生成摘要
* @param data
* @param algorithm
* @return
* @throws Exception
*/
public static String getDigest(String data, String algorithm) throws Exception{
MessageDigest instance = MessageDigest.getInstance(algorithm);
byte[] dataBytes = instance.digest(data.getBytes());
String digest = toHex(dataBytes);
System.out.println("当前加密字符串:" + data + ", 加密方式:" + algorithm + ",加密摘要:" + digest);
return digest;
}
}
获取文件消息摘要
package com.example.password_discipline.digest;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.security.MessageDigest;
public class DigestHexDemo {
public static void main(String[] args) throws Exception {
String data = "aa";
String algorithm = "MD5";
DigestHexDemo.getDigest(data, algorithm);
String sha1 = getDigestFile("D:\\work\\password_discipline\\src\\test\\java\\com\\example\\password_discipline\\digest\\DigestHexDemo.zip", "SHA-1");
System.out.println(sha1);
String sha512 = getDigestFile("D:\\work\\password_discipline\\src\\test\\java\\com\\example\\password_discipline\\digest\\DigestHexDemo.zip", "SHA-512");
System.out.println(sha512);
}
private static String getDigestFile(String filePath, String algorithm) throws Exception{
FileInputStream fis = new FileInputStream(filePath);
int len;
byte[] buffer = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ( (len = fis.read(buffer))!=-1){
baos.write(buffer,0,len);
}
// 获取消息摘要对象
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
// 获取消息摘要
byte[] digest = messageDigest.digest(baos.toByteArray());
System.out.println("密文的字节长度:"+digest.length);
return toHex(digest);
}
public static String toHex(byte[] digest){
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
String temp = Integer.toHexString(b & 0xff);
if(temp.length() == 1){
sb.append("0" + temp);
}else {
sb.append(temp);
}
}
return sb.toString();
}
/**
* 生成摘要
* @param data
* @param algorithm
* @return
* @throws Exception
*/
public static String getDigest(String data, String algorithm) throws Exception{
MessageDigest instance = MessageDigest.getInstance(algorithm);
byte[] dataBytes = instance.digest(data.getBytes());
String digest = toHex(dataBytes);
System.out.println("当前加密字符串:" + data + ", 加密方式:" + algorithm + ",加密摘要:" + digest);
return digest;
}
}
运行程序 ,获取 sha-1 和 sha-512 的值
使用 sha-1 算法,可以实现秒传功能,不管咱们如何修改文件的名字,最后得到的值是一样的
运行程序 ,获取 sha-1 和 sha-512 的值
如果原文修改了,那么sha-1值 就会不一样
运行结果:
总结
- MD5算法 : 摘要结果16个字节, 转16进制后32个字节
- SHA1算法 : 摘要结果20个字节, 转16进制后40个字节
SHA256算法 : 摘要结果32个字节, 转16进制后64个字节
SHA512算法 : 摘要结果64个字节, 转16进制后128个字节.
推荐同系列文章
keytool openssl : https://blog.csdn.net/xiaozhegaa/article/details/109602118
密码学 ~ 数字签名: https://blog.csdn.net/xiaozhegaa/article/details/109601966
密码学 ~ 非对称加密 RSA ECC: https://blog.csdn.net/xiaozhegaa/article/details/109601632
密码学 ~ 消息摘要: https://blog.csdn.net/xiaozhegaa/article/details/109601148
对称加密、DES加解密、AES加解密、Base64加解密: https://blog.csdn.net/xiaozhegaa/article/details/109595399