Java HMAC returns 不同 mac 当调用相同的值时
Java HMAC returns different mac when called on same value
当尝试使用 HMAC 获取 mac 来验证请求的真实性时,我的函数总是 returns 不同的 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 byte[]
数组的 toString()
方法。
来自 Oracle's Java 8 Base64.Encoder
documentation for its encode()
method:
public byte[] encode(byte[] src)
Encodes all bytes from the specified byte array into a newly-allocated
byte array using the Base64 encoding scheme. The returned byte array
is of the length of the resulting bytes.
Parameters:
src
- the byte array to encode
Returns:
A newly-allocated byte array containing the resulting encoded
bytes.
注意 return 类型是 byte[]
.
当您将对象与字符串连接时,如
System.out.println("(client) MAC "+Base64.getEncoder().encode(res));
您使用 toString()
方法将该对象转换为 Java String
.
根据 String
Java documentation(加粗我的):
The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the StringBuilder
(or StringBuffer
) class and its append method. String conversions are implemented through the method toString
, defined by Object and inherited by all classes in Java.
Java 原始数组的 toString()
方法打印数组的 类型 然后是地址。
因此:
(client) MAC [B@7563b5d
[B
表示“byte[]
数组”,@7563b5d
可能是 byte[]
[=64= 的地址(或其他一些 JVM 记帐标记) ] Object
.
如果要打印 Java 基本数组(例如 byte[]
数组)的 CONTENTS您需要使用 java.util.Arrays.toString()
method.
之一
当尝试使用 HMAC 获取 mac 来验证请求的真实性时,我的函数总是 returns 不同的 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 byte[]
数组的 toString()
方法。
来自 Oracle's Java 8 Base64.Encoder
documentation for its encode()
method:
public byte[] encode(byte[] src)
Encodes all bytes from the specified byte array into a newly-allocated byte array using the Base64 encoding scheme. The returned byte array is of the length of the resulting bytes.
Parameters:
src
- the byte array to encodeReturns:
A newly-allocated byte array containing the resulting encoded bytes.
注意 return 类型是 byte[]
.
当您将对象与字符串连接时,如
System.out.println("(client) MAC "+Base64.getEncoder().encode(res));
您使用 toString()
方法将该对象转换为 Java String
.
根据 String
Java documentation(加粗我的):
The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the
StringBuilder
(orStringBuffer
) class and its append method. String conversions are implemented through the methodtoString
, defined by Object and inherited by all classes in Java.
Java 原始数组的 toString()
方法打印数组的 类型 然后是地址。
因此:
(client) MAC [B@7563b5d
[B
表示“byte[]
数组”,@7563b5d
可能是 byte[]
[=64= 的地址(或其他一些 JVM 记帐标记) ] Object
.
如果要打印 Java 基本数组(例如 byte[]
数组)的 CONTENTS您需要使用 java.util.Arrays.toString()
method.