Projet

Général

Profil

0001-systempayv2-implement-HMAC-SHA256-signature-46658.patch

Serghei Mihai, 15 septembre 2020 15:25

Télécharger (4,43 ko)

Voir les différences:

Subject: [PATCH] systempayv2: implement HMAC SHA256 signature (#46658)

 eopayment/systempayv2.py  | 25 +++++++++++++++++++++----
 tests/test_systempayv2.py | 16 ++++++++++++++++
 2 files changed, 37 insertions(+), 4 deletions(-)
eopayment/systempayv2.py
15 15
# You should have received a copy of the GNU Affero General Public License
16 16
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 17

  
18
import base64
18 19
import pytz
19 20
import datetime as dt
20 21
import hashlib
22
import hmac
21 23
import string
22 24
from six.moves.urllib import parse as urlparse
23 25
import warnings
......
270 272
            {'name': 'secret_production',
271 273
                'caption': _(u'Secret pour la configuration de PRODUCTION'),
272 274
                'validation': lambda value: str.isalnum(value), },
275
            {'name': 'signature_algo',
276
                'caption': _(u'Algorithme de signature'),
277
                'default': 'hmac_sha256',
278
                'choices': (
279
                    ('sha1', 'SHA-1'),
280
                    ('hmac_sha256', 'HMAC-SHA-256'),
281
                )},
273 282
            {
274 283
                'name': 'manual_validation',
275 284
                'caption': 'Validation manuelle',
......
462 471
            test=test)
463 472
        return response
464 473

  
474
    def sha1_sign(self, secret, signed_data):
475
        return hashlib.sha1(signed_data).hexdigest()
476

  
477
    def hmac_sha256_sign(self, secret, signed_data):
478
        digest = hmac.HMAC(secret, digestmod=hashlib.sha256, msg=signed_data).digest()
479
        return base64.b64encode(digest)
480

  
465 481
    def signature(self, fields):
466 482
        self.logger.debug('got fields %s to sign' % fields)
467 483
        ordered_keys = sorted(
468 484
            [key for key in fields.keys() if key.startswith('vads_')])
469 485
        self.logger.debug('ordered keys %s' % ordered_keys)
470 486
        ordered_fields = [force_byte(fields[key]) for key in ordered_keys]
471
        secret = getattr(self, 'secret_%s' % fields['vads_ctx_mode'].lower())
487
        secret = force_byte(getattr(self, 'secret_%s' % fields['vads_ctx_mode'].lower()))
472 488
        signed_data = b'+'.join(ordered_fields)
473
        signed_data = b'%s+%s' % (signed_data, force_byte(secret))
489
        signed_data = b'%s+%s' % (signed_data, secret)
474 490
        self.logger.debug(u'generating signature on «%s»', signed_data)
475
        sign = hashlib.sha1(signed_data).hexdigest()
491
        sign_method = getattr(self, '%s_sign' % self.signature_algo)
492
        sign = sign_method(secret, signed_data)
476 493
        self.logger.debug(u'signature «%s»', sign)
477
        return sign
494
        return force_text(sign)
tests/test_systempayv2.py
31 31
    'vads_site_id': u'12345678',
32 32
    'vads_ctx_mode': u'TEST',
33 33
    'vads_trans_date': u'20090501193530',
34
    'signature_algo': 'sha1'
34 35
}
35 36

  
36 37

  
......
80 81
    assert response.transaction_date
81 82
    assert response.transaction_date.isoformat() == '2020-03-30T16:25:30+00:00'
82 83

  
84
    PARAMS['signature_algo'] = 'hmac_sha256'
85
    p = Payment(PARAMS)
86
    assert p.signature(qs) == 'aHrJ7IzSGFa4pcYA8kh99+M/xBzoQ4Odnu3f4BUrpIA='
87
    response_qs = 'vads_amount=1042&vads_auth_mode=FULL&vads_auth_number=3feadf' \
88
                  '&vads_auth_result=00&vads_capture_delay=0&vads_card_brand=CB' \
89
                  '&vads_card_number=497010XXXXXX0000' \
90
                  '&vads_payment_certificate=582ba2b725057618706d7a06e9e59acdbf69ff53' \
91
                  '&vads_ctx_mode=TEST&vads_currency=978&vads_effective_amount=1042' \
92
                  '&vads_site_id=70168983&vads_trans_date=20161013101355' \
93
                  '&vads_trans_id=226787&vads_trans_uuid=4b5053b3b1fe4b02a07753e7a' \
94
                  '&vads_effective_creation_date=20200330162530' \
95
                  '&signature=PeU30M6ilqwhligBAIMQIR3yqxWFGZHJ8Hwtb%2B3IrOM%3D'
96
    response = p.response(response_qs)
97
    assert response.signed
98

  
83 99
    # bad response
84 100
    with pytest.raises(ResponseError, match='missing signature, vads_ctx_mode or vads_auth_result'):
85 101
        p.response('foo=bar')
86
-