Exemple #1
0
def generate_callback_data(
    amount=100,
    sale_order_id=1,
    ref_id=1,
    res_code=1,
    res_message=1,
    pay_gate_trans_id=1,
    rrn=1,
    last_four_digit_of_pan=1,
):
    rijndael = RijndaelCbc(
        key=base64.b64decode(config["key"]),
        iv=base64.b64decode(config["iv"]),
        padding=Pkcs7Padding(32),
        block_size=32,
    )
    data_array = [
        str(amount),  # Transaction amount
        str(sale_order_id),  # Transaction Order ID
        str(ref_id),  # Transaction ID
        str(res_code),  # Result Code
        str(res_message),  # Result Message
        str(pay_gate_trans_id),  # Transaction inquiry id
        str(rrn),  # Bank Reference ID
        str(last_four_digit_of_pan),  # Last four digits of payer card ID
    ]
    return {
        "ReturningParams":
        base64.b64encode(rijndael.encrypt(",".join(data_array).encode()))
    }
 def encrypt(self, plainText):
     encryptor = RijndaelCbc(self.key,
                             self.encryptIV,
                             padding=ZeroPadding(BLOCK_SIZE),
                             block_size=BLOCK_SIZE)
     encText = encryptor.encrypt(plainText)
     self.encryptIV = encText[-BLOCK_SIZE:]
     return encText
Exemple #3
0
 def encrypt(self, plain_data: Union[str, bytes]) -> bytes:
     if isinstance(plain_data, str):
         plain_data = bytes(plain_data, encoding="latin_1")
     cbc = RijndaelCbc(key=self.key,
                       iv=self.encrypt_init_vector,
                       padding=ZeroPadding(self.BLOCK_SIZE),
                       block_size=self.BLOCK_SIZE)
     encrypted_data = cbc.encrypt(plain_data)
     self.encrypt_init_vector = encrypted_data[-self.BLOCK_SIZE:]
     return encrypted_data
def encrypt(iv, key, block_size, plaintext):

    rijndael_cbc = RijndaelCbc(
        key=key,  # if it is a string we can use base64.b64decode(key),
        iv=iv,
        padding=ZeroPadding(block_size),
        block_size=block_size)
    ciphertext = rijndael_cbc.encrypt(plaintext)

    return ciphertext
Exemple #5
0
    def test_rijndael_cbc(self):
        key = 'qBS8uRhEIBsr8jr8vuY9uUpGFefYRL2HSTtrKhaI1tk='
        iv = 'kByhT6PjYHzJzZfXvb8Aw5URMbQnk6NM+g3IV5siWD4='
        rijndael_cbc = RijndaelCbc(key=base64.b64decode(key),
                                   iv=base64.b64decode(iv),
                                   padding=ZeroPadding(32),
                                   block_size=32)
        plain_text = b'Mahdi'
        padded_text = plain_text.ljust(32, b'\x1b')
        cipher = rijndael_cbc.encrypt(padded_text)
        cipher_text = base64.b64encode(cipher)
        self.assertEqual(cipher_text,
                         b'1KGc0PMt52Xbell+2y9qDJJp/Yy6b1JR1JWI3f9ALF4=')
        self.assertEqual(rijndael_cbc.decrypt(cipher), padded_text)

        # Long blocks
        plain_text = b'lorem' * 50
        padded_text = plain_text.ljust(32, b'\x1b')
        cipher = rijndael_cbc.encrypt(padded_text)
        self.assertEqual(rijndael_cbc.decrypt(cipher), padded_text)
def encrypt(key, block_size, plaintext):
    iv = key['iv']
    kc = key['kc']
    ki = key['ki']

    rijndael_cbc = RijndaelCbc(
        key=kc,  # if it is a string we can use base64.b64decode(key),
        iv=iv,
        padding=ZeroPadding(block_size),
        block_size=block_size)
    ciphertext = rijndael_cbc.encrypt(plaintext)

    rijndael_cbc = RijndaelCbc(
        key=ki,  # if it is a string we can use base64.b64decode(key),
        iv=iv,
        padding=ZeroPadding(block_size),
        block_size=block_size)

    MAC = rijndael_cbc.encrypt(plaintext)[-block_size:]

    return ciphertext, MAC
Exemple #7
0
    def test_rijndael_cbc(self) -> None:
        key = "qBS8uRhEIBsr8jr8vuY9uUpGFefYRL2HSTtrKhaI1tk="
        iv = "kByhT6PjYHzJzZfXvb8Aw5URMbQnk6NM+g3IV5siWD4="
        rijndael_cbc = RijndaelCbc(
            key=base64.b64decode(key),
            iv=base64.b64decode(iv),
            padding=Pkcs7Padding(32),
            block_size=32,
        )
        with open(Path(__file__).parent / "lorem_ipsum.txt", "rb") as f:
            plain_text = f.read()

        TIMES = 100
        start_time = time.perf_counter()
        for _ in range(TIMES):
            cipher = rijndael_cbc.encrypt(plain_text)
            plain_text = rijndael_cbc.decrypt(cipher)
        end_time = time.perf_counter()
        print(f"\n{TIMES} encryptions in {end_time - start_time:.2f} seconds")
Exemple #8
0
class AsanPardakhtGateway(Gateway):
    """
    Irankish

    TODO: transaction.pan not implemented

    Home: http://asanpardakht.ir/
    Documentation: http://asanpardakht.ir/ipgdownload/ipgdoc.pdf
    """
    __gateway_name__ = 'asan_pardakht'
    __gateway_unit__ = 'IRR'
    __config_params__ = [
        'key', 'iv', 'username', 'password', 'merchant_config_id',
        'callback_url', 'proxies'
    ]
    _server_url = 'https://services.asanpardakht.net/paygate/merchantservices.asmx?WSDL'

    def __init__(self, config):
        super().__init__(config)
        self.rijndael = RijndaelCbc(key=base64.b64decode(config['key']),
                                    iv=base64.b64decode(config['iv']),
                                    padding=Pkcs7Padding(32),
                                    block_size=32)

    def _get_request_payload(self,
                             transaction: Transaction,
                             additional_data: str = '',
                             accounts: List[Tuple[str, str]] = None):
        """
        Get request payload
        :param transaction: 
        :param additional_data: 
        :param accounts: More (Shaba) accounts, Maximum 7 accounts can use. 
               eg: [('shaba1', '100'), ('shaba2', '200'))]
        :return: 
        """
        accounts = [n for account in accounts
                    for n in account] if accounts else []
        return [
            '1',
            self.config['username'],
            self.config['password'],
            str(transaction.order_id),
            str(transaction.amount),
            datetime.now().strftime('%Y%m%d %I%M%S'),
            additional_data,  # Additional data maximum length is 100 characters
            self.config['callback_url'],
            '0'  # Payment id (optional)
        ] + accounts

    def _get_encrypted_request(self, transaction: Transaction):
        return base64.b64encode(
            self.rijndael.encrypt(','.join(
                self._get_request_payload(transaction)).encode()))

    def _parse_callback_data(self, data: dict):
        data = self.rijndael.decrypt(base64.b64decode(
            data['ReturningParams'])).decode()
        exploded_data = data.split(',')
        return dict(
            amount=exploded_data[0],  # Transaction amount
            sale_order_id=exploded_data[1],  # Transaction Order ID
            ref_id=exploded_data[2],  # Transaction ID
            res_code=exploded_data[3],  # Result Code
            res_message=exploded_data[4],  # Result Message
            pay_gate_trans_id=exploded_data[5],  # Transaction inquiry id
            rrn=exploded_data[6],  # Bank Reference ID
            last_four_digit_of_pan=exploded_data[
                7],  # Last four digits of payer card ID
        )

    @property
    def _encrypted_credentials(self):
        return base64.b64encode(
            self.rijndael.encrypt(','.join(
                [self.config['username'], self.config['password']]).encode()))

    def get_redirection(self, transaction) -> Redirection:
        return Redirection(url='https://asan.shaparak.ir/',
                           body_params=dict(RefId=transaction.id,
                                            RedirctToIPGFORM='true'),
                           method='post')

    def request_transaction(self, transaction: Transaction) -> Transaction:
        client = Client(self._server_url)
        if 'proxies' in self.config:
            client.transport.session.proxies = self.config['proxies']
        try:
            params = {
                'merchantConfigurationID': self.config['merchant_config_id'],
                'encryptedRequest': self._get_encrypted_request(transaction)
            }

            result = client.service.RequestOperation(**params)
            if not result:
                raise TransactionError('AsanPardakht: invalid information.')

            if result[0:1] == '0':
                exploded_result = str(result).split(
                    ',')  # Should have two part [XX,YY]
                transaction.id = exploded_result[1]
            else:
                raise TransactionError(
                    'AsanPardakht: invalid information. code: %s' %
                    str(result))

        except zeep_exceptions.Fault:
            raise TransactionError('AsanPardakht: invalid information.')

        except zeep_exceptions.Error:
            raise GatewayNetworkError

        return transaction

    def validate_transaction(self, data: dict) -> Transaction:
        parsed_data = self._parse_callback_data(data)
        transaction = Transaction()
        transaction.id = parsed_data['ref_id']
        transaction.meta = parsed_data
        if int(parsed_data['res_code']) == 0:
            transaction.validate_status = True
        return transaction

    def verify_transaction(self, transaction: Transaction, data):
        try:
            parsed_data = self._parse_callback_data(data)
            params = {
                'merchantConfigurationID':
                int(self.config['merchant_config_id']),
                'encryptedCredentials': self._encrypted_credentials,
                'payGateTranID': parsed_data['pay_gate_trans_id']
            }
            client = Client(self._server_url)
            if 'proxies' in self.config:
                client.transport.session.proxies = self.config['proxies']

            verify_result = int(client.service.RequestVerification(**params))
            if verify_result == 505:
                raise TransactionAlreadyPaidError(
                    'AsanPardakht: transaction already verified')
            elif verify_result != 500:
                raise TransactionError(
                    'AsanPardakht: invalid transaction, %s' % verify_result)

            reconcile_result = int(
                client.service.RequestReconciliation(**params))
            if reconcile_result != 600:
                raise TransactionError(
                    'AsanPardakht: invalid transaction settlement, %s' %
                    reconcile_result)

        except zeep_exceptions.Error:
            raise GatewayNetworkError

        return transaction