title: Various HMAC_SHA256 functions in classic ASP gives different results
body: <p>Somehow I need to generate a hash in Classic ASP which is equivalent to PHP's following function's output:</p>
  
  <pre><code>$hash = hash_hmac('SHA256', $message, pack('H*', $secret));
  </code></pre>
  
  <p>where <code>$message = 'stackoverflow'; $secret = '1234567890ABCDEF';</code>. I tried quite a lot approaches online, but none matches the PHP result:</p>
  
  <pre><code>bcb3452cd48c0f9048e64258ca24d0f3399563971d4a5dcdc531a7806b059e36
  </code></pre>
  
  <p><strong>Method 1: Using dvim_brix_crypto-js-master_VB.asp online (using CrytoJS)</strong></p>
  
  <pre><code>Function mac256(ent, key) 
      Dim encWA
      Set encWA = ConvertUtf8StrToWordArray(ent)
      Dim keyWA
      Set keyWA = ConvertUtf8StrToWordArray(key)
      Dim resWA
      Set resWA = CryptoJS.HmacSHA256(encWA, key)
      Set mac256 = resWA
  End Function
  
  Function ConvertUtf8StrToWordArray(data)
      If (typename(data) = "String") Then
          Set ConvertUtf8StrToWordArray = CryptoJS.enc.Utf8.parse(data)
      Elseif (typename(data) = "JScriptTypeInfo") Then
          On error resume next
          'Set ConvertUtf8StrToWordArray = CryptoJS.enc.Utf8.parse(data.toString(CryptoJS.enc.Utf8)) 
          Set ConvertUtf8StrToWordArray = CryptoJS.lib.WordArray.create().concat(data) 'Just assert that data is WordArray
          If Err.number&gt;0 Then
              Set ConvertUtf8StrToWordArray = Nothing
          End if
          On error goto 0
      Else
          Set ConvertUtf8StrToWordArray = Nothing
      End if
  End Function
  </code></pre>
  
  <p>The script can be found <a href="https://github.com/ictmanagement/redsysHMAC256_API_ASP/blob/master/include/dvim_brix_crypto-js-master_VB.asp" rel="nofollow noreferrer">here</a>. This method gives:</p>
  
  <pre><code>c8375cf0c0db721ecc9c9b3a034284117d778ee8594285196c41d5020917f78c
  </code></pre>
  
  <hr>
  
  <p><strong>Method 2: Pure Classic ASP Approach</strong></p>
  
  <pre><code>Public Function HMAC_SHA256(prmKey, prmData)
      Dim theKey : theKey = prmKey
      Dim Block_Size, O_Pad, I_Pad
      Block_Size = 64
      O_Pad = 92 'HEX: 5c'
      I_Pad = 54 'HEX: 36'
  
      Dim iter, iter2
      If Len(theKey) &lt; Block_Size Then
          For iter = 1 to Block_Size - Len(theKey)
              theKey = theKey &amp; chr(0)
          Next
      ElseIf Len(theKey) &gt; Block_Size Then
          theKey = SHA256(theKey)
      End If
  
      Dim o_key_pad : o_key_pad = ""
      Dim i_key_pad : i_key_pad = ""
      For iter = 1 to Block_Size
          o_key_pad = o_key_pad &amp; Chr(Asc(Mid(theKey,iter,1)) xor O_Pad)
          i_key_pad = i_key_pad &amp; Chr(Asc(Mid(theKey,iter,1)) xor I_Pad)
      Next
  
      HMAC_SHA256 = SHA256(o_key_pad &amp; SHA256(i_key_pad &amp; prmData))
  End Function
  result = HMAC_SHA256(secret, message)
  </code></pre>
  
  <p>This method gives:</p>
  
  <pre><code>bc0511316791176484c7d80bc8faaecd8388b75fb97516181ba6b361fd032531
  </code></pre>
  
  <hr>
  
  <p><strong>Method 3: Using Amazon AWS's sha256.wsc (using CrytoJS)</strong></p>
  
  <pre><code>Dim sha
  Set sha = GetObject( "script:" &amp; Server.MapPath("sha256.wsc") )
  sha.hexcase = 0
  result = sha.b64_hmac_sha256(secret, message)
  </code></pre>
  
  <p>The WSC can be found <a href="https://forums.aws.amazon.com/servlet/JiveServlet/download/9-34858-139271-2601/sha256.wsc" rel="nofollow noreferrer">here</a>. This method gives (same result as Method 1):</p>
  
  <pre><code>c8375cf0c0db721ecc9c9b3a034284117d778ee8594285196c41d5020917f78c
  </code></pre>
  
  <hr>
  
  <p>I think the problem is the <code>pack()</code> part, which changes the Hex string to binary. Therefore, I found a way to reproduce the <code>pack()</code> function in ASP:</p>
  
  <pre><code>Dim key2, hexarr, binstr
  key2 = "12 34 56 78 90 AB CD EF"
  hexarr = Split(key2)
  ReDim binarr(UBound(hexarr))
  
  For i = 0 To UBound(hexarr)
    binarr(i) = Chr(CInt("&amp;h" &amp; hexarr(i)))
  Next
  
  binstr = Join(binarr, "")
  </code></pre>
  
  <p>where the <code>key2</code> is the original secret with space added in every 2 characters. By replacing the <code>secret</code> with <code>binstr</code>, the methods now produce:</p>
  
  <pre><code>Method 1: 8ab9e595eab259acb10aa18df7fdf0ecc5ec593f97572d3a4e09f05fdd3aeb8f
  Method 2: d23fcafb41d7b581fdae8c2a4a65bc3b19276a4bd367eda9e8e3de43b6a4d355
  Method 3: 8ab9e595eab259acb10aa18df7fdf0ecc5ec593f97572d3a4e09f05fdd3aeb8f
  </code></pre>
  
  <p>None of the above results is identical to PHP's one. What did I miss now?</p>