虽然这个坑是自己埋的,但还是要分享一波,一是给自己一个深刻的教训,同时也是希望在茫茫人海中,如果你也遇到我同样的问题,能够减少弯路,少踩坑。
事情是这个样子的,在一次签名业务中,需要将签名数据用对方签名系统的秘钥secret,进行HmacSHA256计算。 本地调通以后,部署测试环境后,却发现始终无法签名成功。
发现是因为本地和测试环境HmacSHA256计算结果不同导致。代码如下面所示:
1 /*** 2 * 计算请求签名值 3 * 4 * @param message 待计算的消息 5 * @param secret 密钥 6 * @return HmacSHA256计算后摘要值的Base64编码 7 * @throws Exception 加密过程中的异常信息 8 */ 9 public static String doSignatureBase64(String message, String secret) throws Exception { 10 final String algorithm = "HmacSHA256"; 11 Mac hmacSha256; 12 String digestBase64 = null; 13 try { 14 hmacSha256 = javax.crypto.Mac.getInstance(algorithm); 15 byte[] keyBytes = secret.getBytes("UTF-8"); 16 byte[] messageBytes = message.getBytes("UTF-8"); 17 hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, algorithm)); 18 // 使用HmacSHA256对二进制数据消息Bytes计算摘要 19 byte[] digestBytes = hmacSha256.doFinal(messageBytes); 20 // 把摘要后的结果digestBytes转换成十六进制的字符串 21 // String digestBase64 = Hex.encodeHexString(digestBytes); 22 // 把摘要后的结果digestBytes使用Base64进行编码 23 digestBase64 = new String(Base64.encodeBase64(digestBytes), "UTF-8"); 24 } catch (NoSuchAlgorithmException e) { 25 String msg = MessageFormat.format("不支持此算法: {0}", e.getMessage()); 26 Exception ex = new Exception(msg); 27 ex.initCause(e); 28 throw ex; 29 } catch (UnsupportedEncodingException e) { 30 String msg = MessageFormat.format("不支持的字符编码: {0}", e.getMessage()); 31 Exception ex = new Exception(msg); 32 ex.initCause(e); 33 throw ex; 34 } catch (InvalidKeyException e) { 35 String msg = MessageFormat.format("无效的密钥规范: {0}", e.getMessage()); 36 Exception ex = new Exception(msg); 37 ex.initCause(e); 38 throw ex; 39 } 40 return digestBase64; 41 }
然后开始百度,寻找度娘,看各种资料,网上针对此原因的回复,总结了一下,基本是以下几种原因:
1.获取秘钥secret、加密内容message二进制时没有指定编码,显然代码已指定 UTF-8编码,此种情况排除;
2.加密内容message含有"/n"特殊字符等导致。 这里我message故意传入了数字字符串,即message=“123”。此种情况也排除;
3.本地tomcate、JDK版本问题,后面经过验证也排除了;
4.秘钥本地与测试环境不同。但是我眨眼一看秘钥,测试环境:b579053cagcb421cae82751cb8c7a091、本地环境: b5790530f85b431cae8275a3b8c7a091。一样啊。
所以百思不得其解。 那问题究竟在哪呢?我刚说了,我是眨眼一看,作为程序员,需要的是严谨细致,你以为的一样,我们在这样对比下呢?
测试环境 b579053cagcb421cae82751cb8c7a091
本地环境:b5790530f85b431cae8275a3b8c7a091
卧槽秘钥中间几个字符串不一样。于是呼果断更改了测试环境配置,后面对接成功。回头想想,还是粗心大意呀!!