Skip to content

Commit

Permalink
[FIX] payment_authorize: use SHA-512 instead of MD5 as not supported
Browse files Browse the repository at this point in the history
Authorize.Net is phasing out the MD5 based hash use for transaction response
verification in favor of the SHA-512 based hash utilizing a Signature Key.

Instead of hashing with md5 the transaction key, it is now required to hash
the signature key (binary format) with SHA-512.

Support for MD5 will be dropped the 7th March 2019 for sandbox environment and
the 28th March 2019 for production environment, initially planned for the 14th.

Note that as of February 11, 2019 authorize removed the ability to configure or
update MD5 Hash setting in the Merchant Interface.
Merchants who had this setting configured have been emailed/contacted.

opw-1943030

Usefull links:
https://developer.authorize.net/support/hash_upgrade/
https://support.authorize.net/s/article/What-is-a-Signature-Key
https://support.authorize.net/s/article/MD5-Hash-End-of-Life-Signature-Key-Replacement
https://support.authorize.net/s/article/Do-I-need-to-upgrade-my-transaction-fingerprint-from-HMAC-MD5-to-HMAC-SHA512-and-how

closes odoo#31642

Signed-off-by: Romain Derie (rde) <rde@odoo.com>
  • Loading branch information
rdeodoo authored and remihb committed Mar 28, 2019
1 parent 68d225b commit 06cee7e
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 14 deletions.
13 changes: 11 additions & 2 deletions addons/payment_authorize/models/payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import hashlib
import hmac
import logging
import string
import time
import urlparse

Expand Down Expand Up @@ -54,7 +55,15 @@ def _authorize_generate_hashing(self, values):
values['x_fp_timestamp'],
values['x_amount'],
values['x_currency_code']])
return hmac.new(str(values['x_trans_key']), data, hashlib.md5).hexdigest()

# [BACKWARD COMPATIBILITY] Check that the merchant did update his transaction
# key to signature key (end of MD5 support from Authorize.net)
# The signature key is now '128-character hexadecimal format', while the
# transaction key was only 16-character.
if len(values['x_trans_key']) == 128:
return hmac.new(values['x_trans_key'].decode("hex"), data, hashlib.sha512).hexdigest().upper()
else:
return hmac.new(str(values['x_trans_key']), data, hashlib.md5).hexdigest()

@api.multi
def authorize_form_generate_values(self, values):
Expand Down Expand Up @@ -172,7 +181,7 @@ def create(self, vals):
def _authorize_form_get_tx_from_data(self, data):
""" Given a data dict coming from authorize, verify it and find the related
transaction record. """
reference, trans_id, fingerprint = data.get('x_invoice_num'), data.get('x_trans_id'), data.get('x_MD5_Hash')
reference, trans_id, fingerprint = data.get('x_invoice_num'), data.get('x_trans_id'), data.get('x_SHA2_Hash') or data.get('x_MD5_Hash')
if not reference or not trans_id or not fingerprint:
error_msg = _('Authorize: received data with missing reference (%s) or trans_id (%s) or fingerprint (%s)') % (reference, trans_id, fingerprint)
_logger.info(error_msg)
Expand Down
15 changes: 3 additions & 12 deletions addons/payment_authorize/tests/test_authorize.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# -*- coding: utf-8 -*-

import hashlib
import hmac
import time
import urlparse
import unittest
Expand Down Expand Up @@ -32,15 +30,6 @@ def setUp(self):
@odoo.tests.common.post_install(True)
class AuthorizeForm(AuthorizeCommon):

def _authorize_generate_hashing(self, values):
data = '^'.join([
values['x_login'],
values['x_fp_sequence'],
values['x_fp_timestamp'],
values['x_amount'],
]) + '^'
return hmac.new(str(values['x_trans_key']), data, hashlib.md5).hexdigest()

def test_10_Authorize_form_render(self):
self.assertEqual(self.authorize.environment, 'test', 'test without test environment')

Expand Down Expand Up @@ -84,7 +73,7 @@ def test_10_Authorize_form_render(self):
'x_ship_to_state': None,
}

form_values['x_fp_hash'] = self._authorize_generate_hashing(form_values)
form_values['x_fp_hash'] = self.env['payment.acquirer']._authorize_generate_hashing(form_values)
# render the button
res = self.authorize.render('SO004', 320.0, self.currency_usd.id, values=self.buyer_values)
# check form result
Expand All @@ -108,7 +97,9 @@ def test_20_authorize_form_management(self):
# typical data posted by authorize after client has successfully paid
authorize_post_data = {
'return_url': u'/shop/payment/validate',
# x_MD5_Hash will be empty starting the 28th March 2019
'x_MD5_Hash': u'7934485E1C105940BE854208D10FAB4F',
'x_SHA2_Hash': u'7D3AC844BE8CA3F649AB885A90D22CFE35B850338EC91D1A5ADD819A85FF948A3D777334A18CDE36821DC8F2B42A6E1950C1FF96B52B60F23201483A656195FB',
'x_account_number': u'XXXX0027',
'x_address': u'Huge Street 2/543',
'x_amount': u'320.00',
Expand Down

0 comments on commit 06cee7e

Please sign in to comment.