I'm using the following code to produce an 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
}
I borrowed this from java examples found around the internet.
It produces correct results for any data I've tried as long as there are no newlines in the data I'm signing.
I've been using this tool to verify my hashes: https://www.freeformatter.com/hmac-generator.html
I used the output from the linked hmac generator to create these two test cases:
assert(hmac("key", "data") === "5031fe3d989c6d1537a013fa6e739da23463fdaec3b70137d828e36ace221bd0")
assert(hmac("key", "data\ndata") === "8e64d91f963cf37ccae4768f7546494dd00b362f53a94853f629359c4e47c5e2")
The first test case passed but the second test case fails because hmac
produces: 7ec5edf61abbc95f15ffee94ce47ab8889c6d35e7d04ea2924f6b70e55e31acf
.
I've tested this with various single and multi-line strings and AFAICT it always is wrong when there are newlines and always correct when it's a single line.
What am I doing wrong?