@Renaissance, thanks for your example. As you mentioned, I posted this question originally because it is SIM that I am trying to get working. SIM from what I understand works differently to Accepted Hosted in how the hash works. Your PHP SDK example looks great, but I need to get this working with SIM, at least temporarily.
@xero, @dsstrainer... I am using VB.NET, but I'll try to explain what I've done so far.
Firstly, here is the old code, with MD5...
Dim Random As New Random
Dim Sequence = Random.Next(0, 1000)
Dim TimeStamp = CInt((DateTime.UtcNow - New DateTime(1970, 1, 1)).TotalSeconds)
Dim Fingerprint = GetAuthorizeNetMD5(anTransactionKey, anAPILoginID & "^" & Sequence & "^" & TimeStamp & "^" & Total.ToString("0.##") & "^USD")
When I post my initial transaction off to Authorize.Net, x_fp_sequence is assigned the Sequence, x_fp_timestamp is assigned the TimeStamp and x_fp_hash is assigned the Fingerprint variable.
This is the GetAuthorizeNetMD5 function from the above example, which passes in the Transaction Key, API Login ID, Sequence, TimeStamp, Amount and Currency Code.
Public Shared Function GetAuthorizeNetMD5(ByVal Key, ByVal Value)
Dim HMACkey() As Byte = (New ASCIIEncoding()).GetBytes(Key)
Dim HMACdata() As Byte = (New ASCIIEncoding()).GetBytes(Value)
Dim TempHMACMD5 As New System.Security.Cryptography.HMACMD5(HMACkey)
Dim HMAChash() As Byte = TempHMACMD5.ComputeHash(HMACdata)
Dim Fingerprint = ""
For i = 0 To HMAChash.Length - 1
Fingerprint &= HMAChash(i).ToString("x").PadLeft(2, "0")
Next
Return Fingerprint
End Function
The relay URL then receives back the MD5_Hash value. We then compare this to the MD5 Hash Key similar to the code below...
Public Shared Function AuthorizeNetMD5Matched(MD5HashKey As String, APILoginID As String, TransactionID As String, Amount As Decimal, MD5Hash As String) As Boolean
Dim AmountStr As String = Amount.ToString("0.00")
Dim Unencrypted = String.Format("{0}{1}{2}{3}", MD5HashKey, APILoginID, TransactionID, AmountStr)
Dim MD5 = New System.Security.Cryptography.MD5CryptoServiceProvider()
Dim Hashed = Regex.Replace(BitConverter.ToString(MD5.ComputeHash(ASCIIEncoding.[Default].GetBytes(Unencrypted))), "-", "")
Return Hashed.Equals(MD5Hash)
End Function
If Not PaymentRepository.AuthorizeNetMD5Matched(MD5HashKey, APILoginID, TransactionID, Amount, MD5Hash) Then
' Code to abandon the transaction
End If
So the above example passes into the AuthorizeNetMD5Matched function the MD5 Hash key and then using MD5 it then attempts to match the combination of the API Login, Transaction ID, Amount and the MD5_Hash returned.
Now the above code works with MD5 and the challenge is to know how to update this to work with SHA512.
Firstly, I decided to change how the fingerprint is generated...
Dim Fingerprint = GetAuthorizeNetHMACSHA512(anSignatureKey, anAPILoginID & "^" & Sequence & "^" & TimeStamp & "^" & Total.ToString("0.##") & "^USD")
The code above calls the function below, but instead of passing in the Transaction Key (like with MD5) I instead pass in the Signature Key instead, which I generated within my Sandbox account.
Public Shared Function GetAuthorizeNetHMACSHA512(ByVal key As String, ByVal textToHash As String)
If String.IsNullOrEmpty(Key) Then Throw New ArgumentNullException("HMACSHA512: key", "Parameter cannot be empty.")
If String.IsNullOrEmpty(textToHash) Then Throw New ArgumentNullException("HMACSHA512: textToHash", "Parameter cannot be empty.")
If Key.Length Mod 2 <> 0 OrElse Key.Trim().Length < 2 Then
Throw New ArgumentNullException("HMACSHA512: key", "Parameter cannot be odd or less than 2 characters.")
End If
Try
Dim k As Byte() = Enumerable.Range(0, Key.Length).Where(Function(x) x Mod 2 = 0).[Select](Function(x) Convert.ToByte(Key.Substring(x, 2), 16)).ToArray()
Dim hmac As System.Security.Cryptography.HMACSHA512 = New System.Security.Cryptography.HMACSHA512(k)
Dim HashedValue As Byte() = hmac.ComputeHash((New System.Text.ASCIIEncoding()).GetBytes(textToHash))
Return BitConverter.ToString(HashedValue).Replace("-", String.Empty)
Catch ex As Exception
Throw New Exception("HMACSHA512: " & ex.Message)
End Try
End Function
The above function is a VB.NET equivelent of the example at https://developer.authorize.net/support/hash_upgrade/.
Now, I think this bit so far is correct. I say this because I was getting error 99's on the fingerprint being invalid, but this now works fine.
What I am now struggling to do is compare the x_SHA2_Hash that is returned in the relay response to anything. Page 73 of the SIM guide at https://www.authorize.net/content/dam/authorize/documents/SIM_guide.pdf implies you have to build a hash from 30 of the response fields and compare that, but I can't figure it out.