需求背景
工作中需要使用国密算法获取文件hash值做安全校验。
依赖安装
在pom中添加hutool依赖,注意,只有5.x版本才会有SM3算法支持。
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
<!-- BouncyCastle 加密库 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
代码实现
下面代码是最终版可成功运行的,踩过的坑在下面会介绍,如果能给大家遇到问题时带来一些启发就更好了。
// 静态方法进行手动注册
static {
// 注册BouncyCastle Provider以支持SM3算法
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
Security.addProvider(new BouncyCastleProvider());
log.info("BouncyCastle Provider已注册");
}
}
/**
* 使用SM3算法计算文件的hash值
* @param filePath 文件路径
* @return SM3 hash值(十六进制字符串)
*/
public static String calculateSM3Hash(String filePath) {
try {
File file = new File(filePath);
if (!file.exists() || !file.isFile()) {
log.error("文件不存在或不是有效文件: {}", filePath);
return null;
}
SM3 sm3 = new SM3();
String hash = sm3.digestHex(file);
log.info("文件 {} 的SM3 hash值: {}", filePath, hash);
return hash;
} catch (Exception e) {
log.error("计算文件SM3 hash值失败: {}, 错误信息: {}", filePath, e.getMessage(), e);
// 打印可用的Provider信息用于调试
log.error("当前可用的Security Providers:");
for (java.security.Provider provider : Security.getProviders()) {
log.error("Provider: {} - {}", provider.getName(), provider.getVersion());
}
return null;
}
}
/**
* 使用SM3算法计算文件的hash值
* @param file 文件对象
* @return SM3 hash值(十六进制字符串)
*/
public static String calculateSM3Hash(File file) {
try {
if (file == null || !file.exists() || !file.isFile()) {
log.error("文件对象为null或文件不存在或不是有效文件");
return null;
}
SM3 sm3 = new SM3();
String hash = sm3.digestHex(file);
log.info("文件 {} 的SM3 hash值: {}", file.getAbsolutePath(), hash);
return hash;
} catch (Exception e) {
log.error("计算文件SM3 hash值失败, 错误信息: {}", e.getMessage(), e);
return null;
}
}
/**
* 使用SM3算法计算输入流的hash值
* @param inputStream 输入流
* @return SM3 hash值(十六进制字符串)
*/
public static String calculateSM3Hash(InputStream inputStream) {
try {
if (inputStream == null) {
log.error("输入流为null");
return null;
}
SM3 sm3 = new SM3();
String hash = sm3.digestHex(inputStream);
log.info("输入流的SM3 hash值: {}", hash);
return hash;
} catch (Exception e) {
log.error("计算输入流SM3 hash值失败, 错误信息: {}", e.getMessage(), e);
return null;
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
log.error("关闭输入流失败: {}", e.getMessage(), e);
}
}
}
}
遇到问题
运行时首先遇到:No SuchAlgorithemExcepetion: no such algorithm: SM3 for provider BC
初步判断原因:项目中没有BouncyCastle依赖,需要添加。添加 BouncyCastle依赖,最开始只有hutool依赖,添加完BouncyCastle依赖后需要在static方法中对Provider进行手动注册,修改完后运行还是会报这个错。
百度问题的时候发现了一位前辈发的博文,写的特别清晰:no such algorithm:sm4 for provider BC报错解决方法_no such algorithm: sm4 for provider bc-优快云博客
参考前辈的问题排查方法,在calculateSM3Hash方法中打印了一下BouncyCastleProvider的版本,果然版本打印为1.38,并非我后面引入的高版本,然后排查项目依赖,发现有其它一个依赖中依赖了1.38的低版本,将低版本排除掉就OK了。
4623

被折叠的 条评论
为什么被折叠?



