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:
- https://pycryptodome.readthedocs.io/en/latest/src/cipher/oaep.html
- https://pycryptodome.readthedocs.io/en/latest/src/cipher/classic.html#cbc-mode
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")