Как решить «Ключ AES должен иметь длину 16, 24 или 32 байта» - PullRequest
0 голосов
/ 06 июня 2019

Я пытаюсь создать проект колледжа, в котором я пытаюсь внедрить платежный шлюз на мой сайт.Я использую платежный шлюз Paytm (Индия).Они уже предоставили мне контрольный файл.Но когда я пытаюсь передать идентификатор продавца и идентификатор заказа, я получаю сообщение об ошибке.

Вот обратная трассировка: -

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/orders/create/

Django Version: 2.2
Python Version: 3.7.3
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'crispy_forms',
 'social_django',
 'cart.apps.CartConfig',
 'payment.apps.PaymentConfig',
 'orders.apps.OrdersConfig',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'products',
 'drf_paytm',
 'drfaddons',
 'feedback.apps.FeedbackConfig',
 'users.apps.UsersConfig',
 'shop.apps.ShopConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'social_django.middleware.SocialAuthExceptionMiddleware']



Traceback:

File "/Users/shyambalakrishnan/Dev/trydjango/lib/python3.7/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/Users/shyambalakrishnan/Dev/trydjango/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "/Users/shyambalakrishnan/Dev/trydjango/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/Users/shyambalakrishnan/Dev/trydjango/lib/python3.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  21.                 return view_func(request, *args, **kwargs)

File "/Users/shyambalakrishnan/Dev/trydjango/src/orders/views.py" in order_create
  40.             param_dict['CHECKSUMHASH'] = Checksum.generate_checksum_by_str(param_dict, MERCHANT_KEY)

File "/Users/shyambalakrishnan/Dev/trydjango/src/payTm/Checksum.py" in generate_checksum_by_str
  52.     return __encode__(hash_string, IV, merchant_key)

File "/Users/shyambalakrishnan/Dev/trydjango/src/payTm/Checksum.py" in __encode__
  102.     c = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))

File "/Users/shyambalakrishnan/Dev/trydjango/lib/python3.7/site-packages/Crypto/Cipher/AES.py" in new
  95.     return AESCipher(key, *args, **kwargs)

File "/Users/shyambalakrishnan/Dev/trydjango/lib/python3.7/site-packages/Crypto/Cipher/AES.py" in __init__
  59.         blockalgo.BlockAlgo.__init__(self, _AES, key, *args, **kwargs)

File "/Users/shyambalakrishnan/Dev/trydjango/lib/python3.7/site-packages/Crypto/Cipher/blockalgo.py" in __init__
  141.             self._cipher = factory.new(key, *args, **kwargs)

Exception Type: ValueError at /orders/create/
Exception Value: AES key must be either 16, 24, or 32 bytes long.

Вот мой файл checkum.py:

import base64
import string
import random
import hashlib

from Crypto.Cipher import AES


IV = "@@@@&&&&####$$$$"
BLOCK_SIZE = 16


def generate_checksum(param_dict, merchant_key, salt=None):
    params_string = __get_param_string__(param_dict)
    salt = salt if salt else __id_generator__(4)
    final_string = '%s|%s' % (params_string, salt)

    hasher = hashlib.sha256(final_string.encode())
    hash_string = hasher.hexdigest()

    hash_string += salt

    return __encode__(hash_string, IV, merchant_key)

def generate_refund_checksum(param_dict, merchant_key, salt=None):
    for i in param_dict:
        if("|" in param_dict[i]):
            param_dict = {}
            exit()
    params_string = __get_param_string__(param_dict)
    salt = salt if salt else __id_generator__(4)
    final_string = '%s|%s' % (params_string, salt)

    hasher = hashlib.sha256(final_string.encode())
    hash_string = hasher.hexdigest()

    hash_string += salt

    return __encode__(hash_string, IV, merchant_key)


def generate_checksum_by_str(param_str, merchant_key, salt=None):
    params_string = param_str
    salt = salt if salt else __id_generator__(4)
    final_string = '%s|%s' % (params_string, salt)

    hasher = hashlib.sha256(final_string.encode())
    hash_string = hasher.hexdigest()

    hash_string += salt

    return __encode__(hash_string, IV, merchant_key)


def verify_checksum(param_dict, merchant_key, checksum):
    # Remove checksum
    if 'CHECKSUMHASH' in param_dict:
        param_dict.pop('CHECKSUMHASH')

    # Get salt
    paytm_hash = __decode__(checksum, IV, merchant_key)
    salt = paytm_hash[-4:]
    calculated_checksum = generate_checksum(param_dict, merchant_key, salt=salt)
    return calculated_checksum == checksum

def verify_checksum_by_str(param_str, merchant_key, checksum):
    # Remove checksum
    #if 'CHECKSUMHASH' in param_dict:
        #param_dict.pop('CHECKSUMHASH')

    # Get salt
    paytm_hash = __decode__(checksum, IV, merchant_key)
    salt = paytm_hash[-4:]
    calculated_checksum = generate_checksum_by_str(param_str, merchant_key, salt=salt)
    return calculated_checksum == checksum



def __id_generator__(size=6, chars=string.ascii_uppercase + string.digits + string.ascii_lowercase):
    return ''.join(random.choice(chars) for _ in range(size))


def __get_param_string__(params):
    params_string = []
    for key in sorted(params.keys()):
        if("REFUND" in params[key] or "|" in params[key]):
            respons_dict = {}
            exit()
        value = params[key]
        params_string.append('' if value == 'null' else str(value))
    return '|'.join(params_string)


__pad__ = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
__unpad__ = lambda s: s[0:-ord(s[-1])]


def __encode__(to_encode, iv, key):
    # Pad
    to_encode = __pad__(to_encode)
    # Encrypt
    c = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
    to_encode = c.encrypt(to_encode.encode('utf-8'))
    # Encode
    to_encode = base64.b64encode(to_encode)
    return to_encode.decode("UTF-8")


def __decode__(to_decode, iv, key):
    # Decode
    to_decode = base64.b64decode(to_decode)
    # Decrypt
    c = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
    to_decode = c.decrypt(to_decode)
    if type(to_decode) == bytes:
        # convert bytes array to str.
        to_decode = to_decode.decode()
    # remove pad
    return __unpad__(to_decode)


if __name__ == "__main__":
    params = {
        "MID": "mid",
        "ORDER_ID": "order_id",
        "CUST_ID": "cust_id",
        "TXN_AMOUNT": "1",
        "CHANNEL_ID": "WEB",
        "INDUSTRY_TYPE_ID": "Retail",
        "WEBSITE": "xxxxxxxxxxx"
    }

    print(verify_checksum(
        params, 'xxxxxxxxxxxxxxxx',
        "CD5ndX8VVjlzjWbbYoAtKQIlvtXPypQYOg0Fi2AUYKXZA5XSHiRF0FDj7vQu66S8MHx9NaDZ/uYm3WBOWHf+sDQAmTyxqUipA7i1nILlxrk="))

    print(generate_checksum(params, "xxxxxxxxxxxxxxxx"))

Это моя текущая версия: pycrypto == 2.6.1 pycryptodome == 3.8.1

Мой заказ / views.py:

from django.shortcuts import render
from .models import OrderItem , Order
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from payTm import Checksum
from django.views.decorators.csrf import csrf_exempt
from .forms import OrderCreateForm
from cart.cart import Cart
MERCHANT_KEY = 'my_merchant_key'



@login_required
def order_create(request):
    cart = Cart(request)
    if request.method == 'POST':
        form = OrderCreateForm(request.POST)
        if form.is_valid():
            order = form.save()
            for item in cart:
                OrderItem.objects.create(
                    order=order,
                    product=item['product'],
                    price=item['price'],
                    quantity=item['quantity'],
                    total_price=item['total_price'],
                )
            cart.clear()
            param_dict = {
                'MID': 'my_merchant_id',
                'ORDER_ID': str(order.id),
                'TXN_AMOUNT': str(order.total_cost),
                'CUST_ID': order.email,
                'INDUSTRY_TYPE_ID': 'Retail',
                'WEBSITE': 'WEBSTAGING',
                'CHANNEL_ID': 'WEB',
                'CALLBACK_URL': 'http://127.0.0.1:8000/handlerequest/',
            }
            param_dict['CHECKSUMHASH'] = Checksum.generate_checksum(param_dict, MERCHANT_KEY)
        return render(request, 'paytm.html', {'order': order, 'param_dict': param_dict})

    else:
        form = OrderCreateForm()
        return render(request, 'create.html', {'form': form})

@csrf_exempt
def handlerequest(request,*args,**kwargs):

    return HttpRespone("Done")

Как я могу решитьэта ошибка?Или их файл Checksum.py глючит?

1 Ответ

0 голосов
/ 06 июня 2019

Чтобы решить эту проблему, вы должны сделать ключ длиной 16, 24 или 32 байта. В вашем коде

MERCHANT_KEY = 'my_merchant_key'

здесь длина ключа составляет 15 байт, добавьте символ, чтобы сделать его 16 байт

MERCHANT_KEY = 'my_merchant_key_'

Требуемый размер ключа по стандарту AES должен составлять 128, 192 или 256 бит, что составляет 16, 24 и 32 байта соответственно.

...