问题描述
当尝试使用 HMAC 获取 mac 以验证请求的真实性时,我的函数总是返回不同的 mac,这意味着我无法使用该 mac 是不是我遗漏了什么?
private byte[] hmac(String algorithm,byte[] key,byte[] message) throws NoSuchAlgorithmException,InvalidKeyException {
Mac mac = Mac.getInstance(algorithm);
SecretKeySpec secretKeySpec = new SecretKeySpec(key,"AES");
System.out.println("(client) AES "+secretKeySpec);
mac.init(secretKeySpec);
System.out.println("(client) MESSAGE "+message);
mac.update(message);
byte[]res=mac.doFinal();
System.out.println("(client) MAC "+Base64.getEncoder().encode(res));
return res;
}
算法密钥和消息在我调用它们时总是相同的。算法为“HmacSHA256”
输出:
(client) AES javax.crypto.spec.SecretKeySpec@fffe8334
(client) MESSAGE [B@15557ab5
(client) MAC [B@4ed3db30
(client) AES javax.crypto.spec.SecretKeySpec@fffe8334
(client) MESSAGE [B@15557ab5
(client) MAC [B@7563b5d
解决方法
您隐式使用了 Java toString()
数组的 byte[]
方法。
来自Oracle's Java 8 Base64.Encoder
documentation for its encode()
method:
public byte[] encode(byte[] src)
将指定字节数组中的所有字节编码为新分配的 使用 Base64 编码方案的字节数组。返回的字节数组 是结果字节的长度。
参数:
src
- 要编码的字节数组
退货:
一个新分配的字节数组,包含结果编码 字节。
注意返回类型是 byte[]
。
当你用一个字符串连接一个对象时,如
System.out.println("(client) MAC "+Base64.getEncoder().encode(res));
您使用 toString()
方法将该对象转换为 Java String
。
根据 String
Java documentation(我的粗体):
Java 语言为字符串连接运算符 ( + ) 以及将其他对象转换为字符串提供了特殊支持。字符串连接是通过 StringBuilder
(或 StringBuffer
)类及其 append 方法实现的。 字符串转换是通过方法toString
实现的,由Object定义并被Java中的所有类继承。
Java 原始数组的 toString()
方法打印数组的类型,然后打印它的地址。
因此:
(client) MAC [B@7563b5d
[B
表示“byte[]
数组”,@7563b5d
可能是 byte[]
Java Object
的地址(或其他一些 JVM 记帐标签) .
如果要打印 Java 原始数组(例如 byte[]
数组)的 CONTENTS,则需要使用 java.util.Arrays.toString()
method .