1、SHA 算法家族
SHA(Secure Hash Algorithm,安全散列算法)是一个密码散列函数家族,被美国国家安全局(NSA)设计,并由美国国家标准与技术研究院(NIST)发布为联邦数据处理标准(FIPS)。SHA 算法是基于 MD4 算法实现的,作为 MD 算法的继任者,成为新一代的消息摘要算法的代表。SHA 与 MD 算法不同之处主要在于摘要长度,SHA 算法可以生成一个被称为消息摘要的160位(20字节)散列值,而 MD5 的固定长度为128位(16字节)。
SHA-1 是 SHA 算法家族中的第一个成员,于1995年发布。尽管 SHA-1 的设计相当出色,但近年来密码学家已找到其弱点,并证明可以找到两个不同的消息,它们会产生相同的 SHA-1 散列值,即 SHA-1 存在碰撞(collision)的可能性。因此,SHA-1 的安全性被认为已经不足以用于保护敏感信息,许多组织已经建议或要求使用更强的散列算法,如 SHA-2 或 SHA-3。
SHA-2 是 SHA 算法家族的第二代,包括 SHA-224、SHA-256、SHA-384、SHA-512 以及基于这些的 HMAC、HMAC-based Extract-and-Expand(HMAC-SHA-256/512等)变种。SHA-2 算法家族在 SHA-1 的基础上进行了改进,提供了更高的安全性。
SHA-3 是 SHA 算法家族的最新成员,于 2015 年正式发布。SHA-3 的设计目标是提供一个与 SHA-2 完全不同的散列函数,以增加对量子计算机攻击的抵抗力。SHA-3 算法家族包括 SHA3-224、SHA3-256、SHA3-384 和 SHA3-512 等。
总的来说,SHA 算法家族在密码学中扮演着重要的角色,为数据的完整性验证提供了有力的工具。然而,随着技术的发展和攻击手段的不断更新,选择和使用合适的SHA算法版本对于确保数据的安全性至关重要。
2、使用 SHA 消息摘要
消息摘要是密码学中的一个重要概念,它能够将任意长度的数据转换为固定长度的摘要值,这个摘要值通常是一个较短的字符串。消息摘要算法,也被称作散列算法,是一种单向加密算法,具有不可逆性,即无法从摘要值恢复出原始数据。
消息摘要的特点:
- 固定长度:无论输入的消息有多长,计算出来的消息摘要的长度总是固定的,如SHA的固定长度为160位(20字节)。
- 唯一性:只要输入的消息不同,对其进行摘要以后产生的摘要消息也必不相同;但相同的输入必会产生相同的输出。
- 不可逆性:消息摘要是单向的,无法从摘要值恢复出原始数据。
- 快速计算:消息摘要算法通常能够快速地计算出摘要值,适用于大数据量的处理。
【实例】使用 SHA 算法,生成消息摘要。
(1)创建 SHAUtil 类(SHA消息摘要工具类)。
package com.pjb.util;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
/**
* SHA 消息摘要工具类
* @author pan_junbiao
**/
public class SHAUtil
{
//字符编码
private final static String charsetName = StandardCharsets.UTF_8.name();
/**
* SHA-256 消息摘要
*/
public static String encodeSHA256(String data)
{
String result = null;
try
{
//算法
String algorithm = "SHA-256"; //SHA家族:SHA-1、SHA-224、SHA-256、SHA-384、SHA-512
//创建消息摘要对象
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
//执行消息摘要算法
byte[] digestBytes = messageDigest.digest(data.getBytes(charsetName));
//将指定byte数组转换成16进制字符串,否则输出的结果是一串乱码
result = byteToHexString(digestBytes);
} catch (Exception ex)
{
ex.printStackTrace();
}
return result;
}
/**
* 将指定byte数组转换成16进制字符串
*/
private static String byteToHexString(byte[] b)
{
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < b.length; i++)
{
//把密文转换成16进制
String hex = Integer.toHexString(b[i] & 0xFF);
//如果密文的长度只有1位,则需要再高位进行补0
if (hex.length() == 1)
{
hex = '0' + hex;
}
//拼接字符与转大写字母
hexString.append(hex.toUpperCase());
}
return hexString.toString();
}
}
(2)使用 SHA-256 算法,生成消息摘要。
/**
* SHA-256 消息摘要
*/
@Test
public void testSHA256()
{
String data = "您好,欢迎访问 pan_junbiao的博客";
String encodeSHA256 = SHAUtil.encodeSHA256(data);
//打印结果
System.out.println("原始数据:" + data);
System.out.println("SHA256消息摘要:" + encodeSHA256);
}
执行结果:
2、密码的加密
实际开发应用中,存储用户密码时,通常不会存储明文密码,而是存储密码的 MD5 或 SHA 值。在身份验证过程中,用户通常不会直接发送密码,而是发送密码的摘要值。服务器通过相同的摘要算法计算出的摘要值与数据库中存储的摘要值进行比对,从而验证用户身份。这种方法即使在数据被截获的情况下,也能够保护密码的安全。
【实例】使用 SHA-256 算法,实现密码的加密。
/**
* 使用 SHA-256 进行密码的加密
*/
@Test
public void createPasswordSHA256()
{
String password = "123456"; //原始密码
String salt = "ABCDEFG"; //盐
//使用 SHA-256 算法,加密密码(密码格式:原始密码 + 盐)
String passwordSHA = SHAUtil.encodeSHA256(password + salt);
//打印结果
System.out.println("原始密码:" + password);
System.out.println("SHA256密码加密:" + passwordSHA);
}
执行结果: