md5使用中遇到的一个坑

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数组转成字符串

你可能感兴趣的:(md5使用中遇到的一个坑)