Skip to content

Python

This guide shows you how to decrypt sensitive card details using Python. The decryption process uses Rivest-Shamir-Adleman Optimal Asymmetric Encryption Padding (RSA-OAEP) to unwrap the Advanced Encryption Standard (AES) key. Then Advanced Encryption Standard 256-bit Galois/Counter Mode (AES-256-GCM) is used to decrypt the card data.

Prerequisites

Before you begin, you need:

  • Python 3.7 or later installed on your system
  • The cryptography library installed: shell install cryptography command pip install cryptography
  • Your RSA private key, which was generated when you created the key pair
  • An encrypted response from the View card sensitive details endpoint or the Get card PIN endpoint

Understanding the encrypted response

The View card sensitive details and the Get card PIN endpoints return three base64-encoded values:

Field Description
encrypted_key AES-256 key encrypted with your RSA public key
nonce 12-byte initialization vector for AES-GCM decryption
ciphertext Encrypted card details

Load the RSA private key

Load your PEM-formatted RSA private key using the cryptography library:

from cryptography.hazmat.primitives import serialization

private_key = serialization.load_pem_private_key(
    priv_pem,
    password=None,
)

Decode the base64 values

Convert all three base64-encoded values from the API response:

import base64

encrypted_key = base64.b64decode(payload["encrypted_key"])
nonce = base64.b64decode(payload["nonce"])
ciphertext = base64.b64decode(payload["ciphertext"])

Decrypt the AES key

Use your RSA private key to decrypt the AES key. The decryption uses RSA-OAEP padding with SHA-256:

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding

aes_key = private_key.decrypt(
    encrypted_key,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None,
    )
)

Decrypt the card details

Create an AES-GCM cipher and decrypt the card details. The cryptography library handles the authentication tag automatically:

from cryptography.hazmat.primitives.ciphers.aead import AESGCM

aesgcm = AESGCM(aes_key)
plaintext = aesgcm.decrypt(nonce, ciphertext, None)
card_details = plaintext.decode("utf-8")

Complete decryption code

The following example combines all the steps above into a single reusable function, with error handling:

import base64
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.ciphers.aead import AESGCM


def decrypt_card_details(priv_pem: bytes, payload: dict) -> str:
    # Step 1: Load RSA private key
    private_key = serialization.load_pem_private_key(
        priv_pem,
        password=None,
    )

    # Step 2: Decode base64 values
    encrypted_key = base64.b64decode(payload["encrypted_key"])
    nonce = base64.b64decode(payload["nonce"])
    ciphertext = base64.b64decode(payload["ciphertext"])

    # Step 3: Decrypt the AES key using RSA-OAEP
    aes_key = private_key.decrypt(
        encrypted_key,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None,
        )
    )

    # Step 4: Decrypt using AES-256-GCM
    aesgcm = AESGCM(aes_key)
    plaintext = aesgcm.decrypt(nonce, ciphertext, None)

    return plaintext.decode("utf-8")

Usage example

The following example shows how you can pass your PEM-formatted private key and the encrypted payload from the API response to the DecryptCardDetails function:

private_key = b"""
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA5llQr/KNtRhTn+2LJMwd5H62QUdMZ8Gq25LDpZRaosYbsoxH
... your private key content ...
-----END RSA PRIVATE KEY-----
"""

# Response from the View card sensitive details endpoint
encrypted_payload = {
    "ciphertext": "kJR3z/bVTMTjiXMIQ8ha/eN/69q5vMr1sm6o1iKnCOixCB98tvp4WNsh9YCFXqNEPWfTkuiQ",
    "encrypted_key": "zmhGe7OkCl2e5lNaSU6rw28u1UvzqWyncHc+4fKfn+GRBua+zleDdaMfHctTPqK0...",
    "nonce": "W5lMRrL2yKSyWgfq"
}

card_details = decrypt_card_details(private_key, encrypted_payload)
print("Card details:", card_details)