1.问题发现
项目中使用外部服务,按照外部服务需求,需要进行sign检验。这里sign生成使用到了md5。本来从测试到生产整个流程走下来没有发现任何问题,但是上线后监测数据发现,部分服务调用中返回了“签名校验失败”错误。第一时间想到的就是签名算法出现了问题,跟数据源核对了一下发现问题出现在md5加密上。最终经过一波测试分析发现了问题所在。
2.问题代码
/**
* 对字符串md5加密
*/
public static String getMD5(String str) {
try {
// 生成一个MD5加密计算摘要
MessageDigest md = MessageDigest.getInstance("MD5");
// 计算md5函数
md.update(str.getBytes());
return new BigInteger(1, md.digest()).toString(16);
} catch (Exception e) {
throw new SpeedException("MD5加密出现错误");
}
}
3.错误代码分析
问题点
这里使用BigInteger输出16位字符串,会导致一定的情况下出现丢失0的情况。
4.错误对照代码
public class text{
public static String md5Error(String str){
try {
// 生成一个MD5加密计算摘要
MessageDigest md = MessageDigest.getInstance("MD5");
// 计算md5函数
md.update(str.getBytes());
return new BigInteger(1, md.digest()).toString(16);
} catch (Exception e) {
System.out.println("MD5-1加密时出现异常..." + e);
return null;
}
}
public static String md5Success(String str){
// 生成一个MD5加密计算摘要
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes());
byte[] hash = md.digest();
StringBuilder secpwd = new StringBuilder();
for (int i = 0; i < hash.length; i++) {
int v = hash[i] & 0xFF;
if (v < 16) secpwd.append(0);
secpwd.append(Integer.toString(v, 16));
}
return secpwd.toString();
} catch (NoSuchAlgorithmException e) {
System.out.println("MD5-2加密时出现异常..." + e);
return null;
}
}
public static void main(String[] args){
String s = "a";
System.out.println(md5Error(s));
System.out.println(md5Success(s));
}
}
image.png
5.建议
自己手动将byte数组转成字符串
网友评论