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
1 ACCEPTED SOLUTION

Accepted Solutions

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

 

 

View solution in original post

55 REPLIES 55

Hello, we're using SIM (or more precisely DPM) as well and currently don't have time to upgrade to the Accept Hosted solution.

 

I tried the new hash and it seems no matter what I do, it just does not match with what is returned in the relay POST data. The MD5 hash is still fine, but the SHA2 not.

 

I even tried to run the provided C# example to see if there was any problem with my implementation, but even that returned different hash, than what was sent in the relay response (x_SHA2_Hash field).

 

I used exactly what the upgrade post says to generate the message, i.e. my API Login ID, the returned transaction ID (x_trans_id field) and the returned amount (x_amount field) delimited and wrapped in carets exactly per the article.

keksa
Member

We are using SIM and having the same issue while follwing the steps from https://developer.authorize.net/support/hash_upgrade/

the has does not match computed hash does not match x_SHA2_Hash.

xero
Member

I just found out this am about the upcoming change. Although it does read as the option for the hash will be gone Jan 31,2019, and the ability at a later date to be announced.

 

Currently:

We use DPM

Use our form with field posted like x_fp_sequence,x_fp_hash, x_fp_timestamp etc. Using a relay repsonse from authorize.

 

This is what I did and everything worked on our end. We use PHP:

Through developer account, created a signature key

 

On developer side of our site, I did the rest to test this:

1. Took new signature key and converted hex to dec:

$newKey = base_convert($signatureKey,16,2);

2. Changed our php func:

$hashedVar = hash_hmac('sha512','allthesuff^separated^as^usual^','$newKey ) ;

3. Everything else stays the same, we sent the hashed variable and other vars back to the form then posted that form to authorize.

4. Authorize's relay repsonse wasn't touched on our end

5. successful transaction was done and everything on our end completed as needed. Including the slient post.

 

I wasn't sure what to do about the comparison as mentioned (https://developer.authorize.net/support/hash_upgrade/), but it didn't seem to need it.

 

Our relay response is quite generic:

$response = new AuthorizeNetSIM($apiLoginID, $md5Setting);

if ($response->isAuthorizeNet()) {
    if ($response->approved) {

$redirect_url = '';

   }

else{//declined

$redirect_url = '';

}

echo AuthorizeNetDPM::getRelayResponseSnippet($redirect_url);

}.....

 

That's the basics of it. So was this all is what is needed and not as offsensive as documentation makes it out to be?

 

 

stw
Member

I just found out this am about the upcoming change. Although it does read as the option for the hash will be gone Jan 31,2019, and the ability at a later date to be announced.


Currently:

We use DPM

Use our form with field posted like x_fp_sequence,x_fp_hash, x_fp_timestamp etc. Using a relay repsonse from authorize.


This is what I did and everything worked on our end. We use PHP:

Through developer account, created a signature key


On developer side of our site, I did the rest to test this:

1. Took new signature key and converted hex to dec:

$newKey = base_convert($signatureKey,16,2);

2. Changed our php func:

hash_hmac('sha512','allthesuff^separated^as^usual^','$newKey ) ;

3. Everything else stays the same, we sent the hashed variable and other vars back to the form then posted that form to authorize.

4. Authorize's relay repsonse wasn't touched on our end

5. successful transaction was done and everything on our end completed as needed. Including the slient post.


I wasn't sure what to do about the comparison as mentioned (https://developer.authorize.net/support/hash_upgrade/), but it didn't seem to need it.


Our relay response is quite generic:

$response = new AuthorizeNetSIM($apiLoginID, $md5Setting);

if ($response->isAuthorizeNet()) {
    if ($response->approved) {

$redirect_url = '';

   }

else{//declined

$redirect_url = '';

}

echo AuthorizeNetDPM::getRelayResponseSnippet($redirect_url);

}.....


That's the basics of it. So was this all is what is needed and not as offsensive as documentation makes it out to be?

stw
Member

Can't get this working in SIM.

 

Simply replaced 

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

with

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

and changed from a transaction key to a signature key.

 

But I get Error 99 everytime using my developer account.

If I switch back to md5 and the transaction key, everything works fine.

 

 

 

 

dsstrainer
Contributor

The hash as I understand it has always been optional.  You don’t have to verify the MD5 and going forwards you don’t have to verify the new hash. But the point is you should, so that you are verifying the payment came from Authorize.Net. 

 

Unless I am misunderstanding the PHP example above (2nd post up), you are simply not verifying it. The SIM guide talks about verifying against 30 response fields, but I can’t figure out how. 

I'm having difficulty as well. Are you using your signature key instead of your transaction key? 

 

Anyway, I'm trying to convert the hex key to binary as per the documentation using PHP:

 

base_convert('MySignatureKey',16,2);
 
However, this simply returns this as the binary value which can't possible be correct:
 
0000000000000000000000000000000000000000000000000000000000000000
 
 

You are trying to convert the literal string "MySignatureKey" which why you are getting all zeros.

 

I think the terminology is just confusing here. We aren't talking about the "md5 hash" which as you noted was always optional. This is about the new fingerprint which is also referred to as "x_fp_hash" and used to use the login id and transaction key but now uses login id and signature key. Really don't see the difference as its just a new name for a new key that does the same thing. Typical over-engineering from payment gateway companies.

 

In any case, swapping out the keys and changing the hash algorithm from md5 to sha512 doesn't seem to work for everyone.

 

Also has anyone noticed the huge mistake in the email that Authnet sent out refers to "SHA256" but all the places on the dev site refer to "SHA512". I assume sha512 is correct and they just need to fire their email staff.