1

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?

gregghz
  • 3,925
  • 7
  • 40
  • 69

2 Answers2

2

You can see it needs \r\n in java. The carriage return

Here is what i run and got successful result

enter image description here

and the website string for data on two lines is as below

enter image description here

muasif80
  • 5,586
  • 4
  • 32
  • 45
  • 1
    yes, that fixes it. I generated a hash using `echo -n "data\ndata" | openssl dgst -sha256 -hmac "key"` and my function matches that. – gregghz Jun 11 '20 at 16:38
0

You should be using official NIST test vectors to validate, not results from a random website.

Link with test vectors from NIST: http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip

The HMAC-SHA256 should be the ones with L=32 in that zip file.

More details/info here: This question from Security StackExchange has the correct info:

https://security.stackexchange.com/questions/38411/nist-test-vectors-for-hmac-sha-256

mjuarez
  • 16,372
  • 11
  • 56
  • 73
  • are you saying the examples I'm using are incorrect? – gregghz Jun 11 '20 at 15:47
  • I'm not sure, but you should start with the official test vectors, to make sure you're not trying to validate against possibly wrong examples. – mjuarez Jun 11 '20 at 15:57