当消息中出现换行符时,HMAC SHA-256 不正确
HMAC SHA-256 is incorrect when newlines are present in message
我正在使用以下代码生成 HMAC:
import javax.crypto.{Mac, SecretKey}
def hmac(key: String, data: String): String = {
val algo = "HmacSHA256"
val keySpec = new SecretKeySpec(key.getBytes("UTF-8"), algo)
val mac = Mac.getInstance(algo)
mac.init(keySpec)
toHexString(mac.doFinal(data.getBytes("UTF-8")))
}
def toHexString(bytes: Array[Byte]): String = {
val hexBuffer = new StringBuffer()
bytes.foreach { byte =>
val hex = Integer.toHexString(0xff & byte)
if (hex.length == 1) hexBuffer.append('0')
hexBuffer.append(hex)
}
hexBuffer.toString
}
我从互联网上找到的 java 个例子中借用了这个。
只要我签名的数据中没有换行符,它就会为我尝试过的任何数据生成正确的结果。
我一直在使用这个工具来验证我的哈希值:https://www.freeformatter.com/hmac-generator.html
我使用链接的 hmac 生成器的输出创建了这两个测试用例:
assert(hmac("key", "data") === "5031fe3d989c6d1537a013fa6e739da23463fdaec3b70137d828e36ace221bd0")
assert(hmac("key", "data\ndata") === "8e64d91f963cf37ccae4768f7546494dd00b362f53a94853f629359c4e47c5e2")
第一个测试用例通过但第二个测试用例失败,因为 hmac
产生:7ec5edf61abbc95f15ffee94ce47ab8889c6d35e7d04ea2924f6b70e55e31acf
.
我已经用各种单行和多行字符串和 AFAICT 对此进行了测试,当有换行符时它总是错误的,而当它是单行时总是正确的。
我做错了什么?
您应该使用官方 NIST 测试向量来验证,而不是来自随机网站的结果。
Link 使用来自 NIST 的测试向量:http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
HMAC-SHA256 应该是那个 zip 文件中 L=32 的。
更多 details/info 在这里:
来自 Security StackExchange 的这个问题具有正确的信息:
https://security.stackexchange.com/questions/38411/nist-test-vectors-for-hmac-sha-256
您可以在 java 中看到它需要 \r\n
。 carriage return
这是我 运行 并获得成功的结果
两行数据的网站字符串如下
我正在使用以下代码生成 HMAC:
import javax.crypto.{Mac, SecretKey}
def hmac(key: String, data: String): String = {
val algo = "HmacSHA256"
val keySpec = new SecretKeySpec(key.getBytes("UTF-8"), algo)
val mac = Mac.getInstance(algo)
mac.init(keySpec)
toHexString(mac.doFinal(data.getBytes("UTF-8")))
}
def toHexString(bytes: Array[Byte]): String = {
val hexBuffer = new StringBuffer()
bytes.foreach { byte =>
val hex = Integer.toHexString(0xff & byte)
if (hex.length == 1) hexBuffer.append('0')
hexBuffer.append(hex)
}
hexBuffer.toString
}
我从互联网上找到的 java 个例子中借用了这个。
只要我签名的数据中没有换行符,它就会为我尝试过的任何数据生成正确的结果。
我一直在使用这个工具来验证我的哈希值:https://www.freeformatter.com/hmac-generator.html
我使用链接的 hmac 生成器的输出创建了这两个测试用例:
assert(hmac("key", "data") === "5031fe3d989c6d1537a013fa6e739da23463fdaec3b70137d828e36ace221bd0")
assert(hmac("key", "data\ndata") === "8e64d91f963cf37ccae4768f7546494dd00b362f53a94853f629359c4e47c5e2")
第一个测试用例通过但第二个测试用例失败,因为 hmac
产生:7ec5edf61abbc95f15ffee94ce47ab8889c6d35e7d04ea2924f6b70e55e31acf
.
我已经用各种单行和多行字符串和 AFAICT 对此进行了测试,当有换行符时它总是错误的,而当它是单行时总是正确的。
我做错了什么?
您应该使用官方 NIST 测试向量来验证,而不是来自随机网站的结果。
Link 使用来自 NIST 的测试向量:http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
HMAC-SHA256 应该是那个 zip 文件中 L=32 的。
更多 details/info 在这里: 来自 Security StackExchange 的这个问题具有正确的信息:
https://security.stackexchange.com/questions/38411/nist-test-vectors-for-hmac-sha-256
您可以在 java 中看到它需要 \r\n
。 carriage return
这是我 运行 并获得成功的结果
两行数据的网站字符串如下