Java使用BigInteger计算HmacSHA256结果与C#不一致如何解决?
问题根因
两者的BigInteger转字节数组的默认实现存在两点核心差异:
- 字节序不同:C#的
BigInteger.ToByteArray()输出为小端序,Java的BigInteger.toByteArray()输出为大端序 - 符号位补零规则不同:Java的
BigInteger默认使用补码表示,若正整数的最高有效位为1,会在字节数组最前补一个0x00避免被识别为负数;C#的BigInteger.ToByteArray()不会在数组前额外补零
Java侧修改方案
你需要先把Java的BigInteger转换成和C#对齐的字节数组,再传入HMAC计算即可,参考实现如下:
public static byte[] toCsharpCompatibleBigIntegerBytes(BigInteger value) { byte[] javaBytes = value.toByteArray(); // 移除Java侧补充的前导0 if (javaBytes[0] == 0) { byte[] temp = new byte[javaBytes.length - 1]; System.arraycopy(javaBytes, 1, temp, 0, temp.length); javaBytes = temp; } // 反转字节数组转为小端序,和C#输出对齐 for (int i = 0; i < javaBytes.length / 2; i++) { byte temp = javaBytes[i]; javaBytes[i] = javaBytes[javaBytes.length - 1 - i]; javaBytes[javaBytes.length - 1 - i] = temp; } return javaBytes; }
修改后的HMAC计算代码:
Mac sha256HMAC = Mac.getInstance("HmacSHA256"); // 替换原有的key.toByteArray()为转换后的字节数组 SecretKeySpec secretKey = new SecretKeySpec(toCsharpCompatibleBigIntegerBytes(key), sha256HMAC.getAlgorithm()); sha256HMAC.init(secretKey); // 替换原有的message.toByteArray()为转换后的字节数组 byte[] hmacBytes = sha256HMAC.doFinal(toCsharpCompatibleBigIntegerBytes(message)); System.out.println(">>> HMAC: " + Utils.bytesToHex(hmacBytes));
调整后输出结果就会和C#侧完全一致。
内容的提问来源于stack exchange,提问作者Nick Pham
相关产品推荐
相关产品推荐

