Encriptación de la data

La encriptación de la data es opcional al momento de crear una transacción con tarjeta

Protocolo de Encriptación

Para realizar la encriptación soportamos dos algoritmos:

  • RSA 2048 con PKCS1_OAEP.
  • AES 256 en modo CBC (Cipher-Block Chaining).

Para saber más de estos:

Como encriptar la data:

RSA

Para encriptar la data se tiene que usar el public_key obtenido desde este endpoint.

import base64
import json

from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA


def encrypt_data(public_key: bytes, data: dict) -> str:
    """Encrypts the provided data in json format using the provided public key"""
    str_data = json.dumps(data)
    key = RSA.import_key(public_key)
    cipher = PKCS1_OAEP.new(key)
    encrypted_data = cipher.encrypt(str_data.encode("utf-8"))
    return base64.b64encode(encrypted_data).decode("utf-8")

Ejemplo de uso:

Aquí tenemos un ejemplo, donde se encriptan los datos de tarjeta usando el algoritmo RSA para realizar un cobro único:

import base64
import json
import uuid

import requests
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA

X_ORG_ID = "<X-ORG-ID>"
X_API_KEY = "<X-API-KEY>"
ID_ACCOUNT = "<ID-ACCOUNT>"
ENCRYPTION_KEY = str(uuid.uuid4())  # ESTE VALOR TIENE QUE SER UNICO
SECURE_API_URL = "https://secure.api.trytoku.com"


def encrypt_data(public_key: bytes, data: dict) -> str:
    """Encrypts the provided data in json format using the provided public key"""
    str_data = json.dumps(data)
    key = RSA.import_key(public_key)
    cipher = PKCS1_OAEP.new(key)
    encoded_data = str_data.encode("utf-8")
    encrypted_data = cipher.encrypt(encoded_data)
    return base64.b64encode(encrypted_data).decode("utf-8")


def create_public_key(encryption_key: str) -> str:
  	""" Create the public key using the encryption_key """
    print("Creating public key")
    url = f"{SECURE_API_URL}/public-encryption-keys?encryption_key={encryption_key}"

    headers = {"x-org-id": X_ORG_ID, "x-api-key": X_API_KEY}

    response = requests.request("POST", url, headers=headers)

    print(response.status_code)
    print(response.text)
    response.raise_for_status()

    return response.json()["public_key"]


def send_one_time_po_payment(payload: dict):
  	""" Send request to make a one time payment """
    print("Sending one time payment orchestration")
    print(payload)
    url = "{SECURE_API_URL}/cards/onetime/entry-point"

    headers = {
        "x-org-id": X_ORG_ID,
        "Content-Type": "application/json",
        "x-api-key": X_API_KEY,
    }

    response = requests.request("POST", url, headers=headers, json=payload)

    print(response.status_code)
    response.raise_for_status()
    print(response.json())
    return response.json()


payload = {
    "id_customer": "<ID-CUSTOMER>",
    "toku_product": "payment_orchestration_onetime",
    "id_account": ID_ACCOUNT,
    "transaction_external_id": "<TRANSACTION-EXTERNAL-ID>",
    "engine": "SAAS",
    "id_invoices": ["<ID_INVOICE>"],
    "encryption_key": ENCRYPTION_KEY,
}

CARD_INFORMATION = {
    "number": "<CARD_NUMBER>",
    "verification_value": "<CVV>",
    "month": "<MONTH>",
    "year": "<YEAR>",
    "full_name": "<CARD HOLDER NAME>",
}

# CREATE PUBLIC KEY
public_key = create_public_key(ENCRYPTION_KEY)

# ENCRYPT THE CARD INFORMATION USING THE PUBLIC KEY
encrypted_data = encrypt_data(public_key.encode(), CARD_INFORMATION)

# Add the encrypted card information to the payload
payload["card_information"] = encrypted_data

# Make the one time payment
send_one_time_po_payment(payload)


AES

Para encriptar la data se tiene que usar la secret_key obtenida desde este endpoint

import base64
import json

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad


def encrypt_data(secret_key: bytes, data: dict) -> str:
    """Encrypts the provided data in JSON format using AES-256 (CBC mode)"""
    str_data = json.dumps(data)
    cipher = AES.new(secret_key, AES.MODE_CBC)

    ct_bytes = cipher.encrypt(pad(str_data.encode("utf-8"), AES.block_size))
    iv_bytes = bytes(cipher.iv)
    combined = iv_bytes + ct_bytes

    return base64.b64encode(combined).decode("utf-8")