一、SHA-256算法简介
SHA-2(Secure Hash Algorithm 2),一种散列函数算法标准,由美国国家安全局研发,由美国国家标准与技术研究院(NIST)在2001年发布,属于SHA算法之一,是SHA-1的后继者。其下又分为六个不同的算法标准,包括:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。这些变体除了生成摘要的长度、循环运行的次数等一些细微差异之外,基本结构是一致的。
本文主要介绍SHA-256。
SHA-256(Secure Hash Algorithm 256-bit)是一种广泛使用的安全哈希函数算法,SHA-256是SHA-2系列中的一部分,也被称为SHA-224和SHA-256。
SHA-256的主要目标是提供一种算法,可以将输入(无论长度如何)生成为一个固定长度大小【256位(32字节)】的输出值。这个输出值称为哈希值或信息摘要。可以用于验证数据的完整性和来源。
SHA-256主要用于安全相关的应用,如数字签名、文件校验、检测数据是否被篡改等。
SHA-256算法特点:
- 不可逆性:无法通过散列值反向推导出原始数据;
- 高强度:对于相同的输入,即使改变一个字符也会得到完全不同的散列值;
- 哈希冲突率低:即使SHA-256输出的256位二进制值空间庞大,但仍有可能出现不同的输入得到相同的散列值,这种情况称为哈希冲突。
注意:
- SHA-256本身是一个哈希函数,它并不加密数据,而是生成数据的哈希值(或称消息摘要)。这个哈希值是一个复杂的数字指纹,对于任何给定的输入,它几乎是唯一的。这意味着,即使输入数据只有微小的变化,其哈希值也会发生显著变化。
- SHA-256生成的哈希值是一个固定长度的值,具体为256位(32字节)的二进制数据。然而,在数据库中存储时,我们通常会将这些二进制数据转换为十六进制(0-9, A-F)字符串表示,以便阅读和查询。因此256位二进制数据将转换为64个字符的十六进制字符串来存储VARCHAR(64)。
SHA-256算法的主要步骤如下:
- 初始化一个256位的信息摘要。
- 处理数据块。将数据分成512位的数据块,如果不足512位,则通过填充规则补足。
- 最终摘要。将填充的数据块通过一系列的位操作转换为一个新的信息摘要。
二、SHA-256算法工具类
public class SHA256Utils {
/**
* 使用SHA-256算法计算多个对象(字符串)的联合哈希值
*
* @param inputs 输入的对象数组
* @return 十六进制的哈希值
*/
public static String getSHA256Hex(Object... inputs) {
try {
// 创建MessageDigest实例,初始化为SHA-256算法
MessageDigest md = MessageDigest.getInstance("SHA-256");
// 遍历所有输入字符串,将它们添加到哈希计算中
for (Object input : inputs) {
// 如果为空,则设置为null字符串
String inputStr = input== null ? "null" : input.toString();
md.update(inputStr.getBytes(StandardCharsets.UTF_8));
}
// 计算哈希值
byte[] hash = md.digest();
// 将字节数组转换为十六进制字符串
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
/**
* 验证数据的哈希值是否匹配
*
* @param storedHash 存储的哈希值
* @param inputs 要验证的输入对象数组
* @return 如果哈希值匹配,则返回true;否则返回false
*/
public static boolean verifyHash(String storedHash, Object... inputs) {
String computedHash = getSHA256Hex(inputs);
return computedHash.equals(storedHash);
}
public static void main(String[] args) {
String[] inputs = {"Hello, ", "SHA-256!", " Multiple", " inputs", null};
String hash = getSHA256Hex(inputs);
System.out.println("Combined Hash : " + hash);
System.out.println("Combined Hash1: " + getSHA256Hex("a1"));
System.out.println("Combined Hash2: " + getSHA256Hex("a1", "a2"));
// 假设这是之前存储的哈希值
String storedHash = hash; // 在实际应用中,这将是从某处检索的
// 验证哈希值
boolean isVerified = verifyHash(storedHash, inputs);
System.out.println("Data Verified: " + isVerified);
String[] inputs2 = {"Hello, ", "SHA-256!", " Multiple", " inputs"};
boolean isVerified2 = verifyHash(storedHash, inputs2);
System.out.println("Data Verified2: " + isVerified2);
// 修改输入后尝试验证
String[] modifiedInputs = {"Hello, ", "SHA-256?!", " Modified", " inputs"};
boolean isModifiedVerified = verifyHash(storedHash, modifiedInputs);
System.out.println("Modified Data Verified: " + isModifiedVerified);
System.out.println("Modified Data Verified2: " + verifyHash(null, modifiedInputs));
}
}
– 求知若饥,虚心若愚。