cancel
Showing results for 
Search instead for 
Did you mean: 

Upgrading MD5 to new hash (SIM)

I am trying to upgrade from MD5 to the new hash method as described here:- https://developer.authorize.net/support/hash_upgrade

 

We are using SIM still do in addition I read the guide at https://support.authorize.net/s/article/Do-I-need-to-upgrade-my-transaction-fingerprint-from-HMAC-MD....  This second link seems to talk about generating the fingerprint with more values than the first link above does, more similar to how wo do MD5 currently.

 

 

I’m having trouble validating matching the value I submit to what is returned in the response.  Note: We need this to work with SIM as we can’t upgrade to the new API currently.

 

I am creating the hash using the new method and submitting it to the x_fp_hash during the post.  I assume my x_fp_hash is correct because I was previously getting error 99’s which is a fingerprint error, but no longer do.

 

The response comes back after doing the payment in the x_SHA2_Hash field.  It doesn't compare to x_fp_hash.  So I thought there is more to this.  Looking in the SIM guide, on page 73 at https://www.authorize.net/content/dam/authorize/documents/SIM_guide.pdf it mentions generating a hash from 30 fields.

 

I've done this and it still doesn't compare to x_SHA2_Hash.  So I assume I am doing something wrong, but not sure.  The documentation doesn't really give any examples of how to do this so I am uncertain what my issue is.

cwdsl
Contributor
55 REPLIES 55

Same.

OK weirdly, I couldn't pass the value byref but works fine byval

fingerprint now working fine with sha512 in php

 

changed

 

return hash_hmac("md5", $loginid . "^" . $sequence . "^" . $tstamp . "^" . $amount . "^" . $currency, $x_tran_key);

 

 

to

 

$x_tran_key = base_convert($x_tran_key,16,2);
return hash_hmac('sha512', $loginid . "^" . $sequence . "^" . $tstamp . "^" . $amount . "^" . $currency, $x_tran_key);

 

but for some reason it wouldn't allow me to use base_convert as an inline function:

return hash_hmac('sha512', $loginid . "^" . $sequence . "^" . $tstamp . "^" . $amount . "^" . $currency, base_convert($x_tran_key,16,2));

 

dsstrainer
Contributor

@dsstrainer, in your example above where you call the hash_hmac function, you seem to be passing in the transaction key.  Should it not be the Signature Key?  In step 4 at https://developer.authorize.net/support/hash_upgrade/ it mentions the signature key (not the Transaction Key which was the old way).

 

As a side note, as anyone got the validation of the x_SHA2_Hash working in C# or VB.NET?  I've still trying to validate it against the 30 fields in the response and it never seems to work.

 

 

I am using the signature key as the value despite the name of the variable

@xero, many thanks for this.  Further down in that post I saw you gave you examples of test values...

 

key  "9C5A4D2AFE1D1D5DB3A8FC4C95CDCF49E2B052B4220D0624C54C1C662194BDEF8FE0EA27B313FA62328D9500D123B9DD3CE06644508803ACD04DAEDB24C5D122"

 

text = "^0^false^3^^^^P^^^1.99^^^^^^^^^^^^^^^^^^^^^"

 

x_SHA2_Hash= "4038397293CE5DBBFD5AD21B2F96FF5B6E32EA9F56D310AA95D1D091EBEAD1C35FE5AF96111D7911B2816FCE0DBA2D41A5BD268F766183DC8F3B750B22F68E16"

 

When I use these test values my code is working perfectly and it matches the x_SHA2_Hash.  However my response does work...

 

Raw Response: 

 

x_response_code=1&x_response_reason_code=1&x_response_reason_text=This+transaction+has+been+approved.&x_avs_code=Y&x_auth_code=XL2BHF&x_trans_id=40024124211&x_method=CC&x_card_type=Visa&x_account_number=XXXX0027&x_first_name=John&x_last_name=Smith&x_company=&x_address=Street&x_city=City&x_state=AK&x_zip=Zip&x_country=United+States&x_phone=&x_fax=&x_email=&x_invoice_num=593&x_description=Trafford%2bCentre%2b%2b-%2bShopping%2bat%2bthe%2bTrafford%2bCentre%2b(19%252f01%252f2019)&x_type=auth_capture&x_cust_id=&x_ship_to_first_name=&x_ship_to_last_name=&x_ship_to_company=&x_ship_to_address=&x_ship_to_city=&x_ship_to_state=&x_ship_to_zip=&x_ship_to_country=&x_amount=1.99&x_tax=0.00&x_duty=0.00&x_freight=0.00&x_tax_exempt=FALSE&x_po_num=&x_MD5_Hash=96F59D4AE68A0E786938D94414CD88A0&x_SHA2_Hash=9FC2FCA7FFB81C0C4CEA7FEBD38C2A6D44FA32E64E33542DC4928CE5F01B5B984905BB887D9AA11ACC6F5ABAA9FD4BD7FBB0D50F15594DE8DE054C1DCABFCD8E&x_cvv2_resp_code=P&x_cavv_response=2&x_test_request=false

 

As I understand it my text to hash would be...

 

^40024124211^false^1^XL2BHF^P^2^Y^CC^XXXX0027^1.99^^John^Smith^Street^City^AK^Zip^United+States^^^^^^^^^^^^593^

 

Correct?

 

So the x_SHA2_Hash in the response is... is 9FC2FCA7FFB81C0C4CEA7FEBD38C2A6D44FA32E64E33542DC4928CE5F01B5B984905BB887D9AA11ACC6F5ABAA9FD4BD7FBB0D50F15594DE8DE054C1DCABFCD8E

 

My Signature is...

5FE3171BBEE36A864E16117564CE3D5DDB237A580FE535856A76C28C325F879B24E68B48A3BC4E6E5BCE0113EA8D219B0469E1444A663E79ED798E16E79609B7

 

When I pass these two values into the function it does not return the same value as the x_SHA2_Hash.  This example also use the same test amount of 1.99, sequence of 2627 as in your example.

 

The hashed value I am getting is:

 

E845DA2C760C2C392CEEE313332F35150AD7104CB2D6CE5950DD5AB9865F3A0A4B1C980A3814FD03ED6546683B561253FC46E30A0DE8FD70F66BC94868B51240 which clearly is not a match.

@xero, follow up... I've now got it working!

 

I figured out it way the name and address that wasn't matching.  I saw in my response there were + symbols instead of a space in the address fields.  This was because I was doing a Request.Form.ToString instead of doing the Request.Params on each field individually like in your example.  So I've now got it working.  Many thanks to you for your examples.

For others that may find this useful, below is my code to get it working in VB.NET with the SIM integration, with thanks to a few members on this forum...

 

Firstly I have a function to do the SHA512 (VB.NET modified version of the C# example Authorize.Net created)...

 

 

Public Shared Function GetAuthorizeNetHMACSHA512(ByVal key As String, ByVal textToHash As String)

    If String.IsNullOrEmpty(key) Then Return ""
    If String.IsNullOrEmpty(textToHash) Then Return ""

    If Key.Length Mod 2 <> 0 OrElse Key.Trim().Length < 2 Then
        Return ""
    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
        Return ""
    End Try

End Function

 

I generate the Sequence and TimeStamp as I always have done.  The Fingerprint is generated by calling the new SHA512 function.  This function passes in the API Login ID, Sequence, TimeStamp and Amount as follows and the Signature Key as the hash...

 

 

Dim Random As New Random
Dim Sequence = Random.Next(0, 1000)
Dim TimeStamp = CInt((DateTime.UtcNow - New DateTime(1970, 1, 1)).TotalSeconds)
Dim Fingerprint = GetAuthorizeNetHMACSHA512(anSignatureKey, anAPILoginID & "^" & Sequence & "^" & TimeStamp & "^" & Total.ToString("0.##") & "^")

 

When doing the initial post to Authorize.Net I generate the x_fp_sequencex_fp_timestamp and x_fp_hash from the Sequence, TimeStamp and Finterprint variables shown above.

 

In the Relay Response URL I build up the text I want to hash based on the 30 reponse fields described on page 73 of the SIM guide.  I then SHA512 this value using the same Signature Key.  I finally get the x_SHA2_Hash from the response and compare this to the value I SHA512 hashed and deal with as appropriate...

 

Dim TextToHash As String = String.Join("^", Request.Params("x_trans_id"), Request.Params("x_test_request"), Request.Params("x_response_code"), Request.Params("x_auth_code"), Request.Params("x_cvv2_resp_code"), Request.Params("x_cavv_response"), Request.Params("x_avs_code"), Request.Params("x_method"), Request.Params("x_account_number"), Request.Params("x_amount"), Request.Params("x_company"), Request.Params("x_first_name"), Request.Params("x_last_name"), Request.Params("x_address"), Request.Params("x_city"), Request.Params("x_state"), Request.Params("x_zip"), Request.Params("x_country"), Request.Params("x_phone"), Request.Params("x_fax"), Request.Params("x_email"), Request.Params("x_ship_to_company"), Request.Params("x_ship_to_first_name"), Request.Params("x_ship_to_last_name"), Request.Params("x_ship_to_address"), Request.Params("x_ship_to_city"), Request.Params("x_ship_to_state"), Request.Params("x_ship_to_zip"), Request.Params("x_ship_to_country"), Request.Params("x_invoice_num"))
Dim HashedValue As String = PaymentRepository.GetAuthorizeNetHMACSHA512(anSignatureKey, "^" & TextToHash & "^")
Dim x_SHA2_Hash As String = Request.Params("x_SHA2_Hash").ToString()

If HashedValue <> x_SHA2_Hash Then
    ' Do as appropriate if they don't match
End If

 

 

Here's a correction to @stw's PHP SIM solution

 

In step 1, base_convert does not work.

 

For PHP 5.4+, use instead:

hex2bin(SIGNATURE_KEY);

as suggested by @Renaissance

 

For earlier versions of PHP, you can use:

pack("H*" , SIGNATURE_KEY)

 

@capturewiz I'm not sure that php's hex2bin  is the correct function. 

 

According to Authorize:

https://support.authorize.net/s/article/What-is-a-Signature-Key

NOTE: The Merchant Interface will present the Signature Key in a 128-character hexadecimal format. However, developers will need to convert the Signature Key into binary format to use it. Please consult the documentation for your scripting language or development framework, for details on how to convert long hexadecimal strings to binary.

 

And php.net:

http://us1.php.net/manual/en/function.hex2bin.php

Caution

This function does NOT convert a hexadecimal number to a binary number. This can be done using the base_convert() function.

 

When testing, using base_convert it did work.

 

Does hex2bin work as well? The instructions from both Authorize and php seem straight forward, and the process worked. What did I miss?