Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.nuvion.co/llms.txt

Use this file to discover all available pages before exploring further.

How to encrypt payment data before sending it to Nuvion’s API.

Overview

All sensitive payment data (card numbers, CVV, etc.) must be encrypted using RSA-OAEP with SHA-256 before being sent to the API. Why encryption? Encrption is necessary for the following reasons:
  • Protects card data in transit (even over HTTPS)
  • Prevents data from being logged or cached
  • Ensures only Nuvion can decrypt the sensitive data
  • PCI DSS compliance

Getting Your Public Key

To Get your RSA Public Key in PEM format:
  • Login into your approved Nuvion account
  • Navigate to Settings > “Developers”
  • Click on Create Key button to create API key
  • The public encryption key will be displayed along the secret key. The encryption key is copiable and can be used to encrypt card data before sending it to Nuvion’s API.

Encryption Algorithm

  • Algorithm: RSA-OAEP
  • Hash Function: SHA-256
  • Padding: OAEP (Optimal Asymmetric Encryption Padding)
  • Encoding: Base64

Card Data Validation

Before encrypting, validate the card data:

Card Number

  • Remove all spaces and dashes
  • Must be 13-19 digits
  • Should pass Luhn check (checksum validation)

Expiry Date

  • Month: 01-12 (two digits)
  • Year: YYYY format (e.g., 2025)
  • Must be in the future

CVV

  • 3 digits for most cards
  • 4 digits for American Express

Cardholder Name

  • Minimum 1 character
  • Only letters, spaces, hyphens, and apostrophes

Encrypting Card Data

Use the RSA public key to encrypt card data using RSA-OAEP with SHA-256. Encrypt the following card data as a JSON object:
{
  "card_number": "4111111111111111",
  "expiry_month": "12",
  "expiry_year": "2025",
  "cvv": "123",
  "cardholder_name": "John Doe"
}

Implementation Examples

Node.js Example
const crypto = require('crypto');

function encryptCardData(cardData, publicKeyPem) {
  // Convert card data to JSON string
  const jsonString = JSON.stringify(cardData);
  
  // Encrypt using RSA-OAEP with SHA-256
  const encrypted = crypto.publicEncrypt(
    {
      key: publicKeyPem,
      padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
      oaepHash: 'sha256'
    },
    Buffer.from(jsonString)
  );
  
  // Return base64-encoded string
  return encrypted.toString('base64');
}

// Usage
const publicKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----`;

const cardData = {
  card_number: '4111111111111111',
  expiry_month: '12',
  expiry_year: '2025',
  cvv: '123',
  cardholder_name: 'John Doe'
};

const encryptedData = encryptCardData(cardData, publicKey);
console.log(encryptedData);
// Output: "tbjH0nx6WaEkzHOjgw2crsusmVBuL8s+PxWF..."
Python (cryptography)
import json
import base64
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.backends import default_backend

def encrypt_card_data(card_data, public_key_pem):
    # Load the public key
    public_key = serialization.load_pem_public_key(
        public_key_pem.encode(),
        backend=default_backend()
    )
    
    # Convert card data to JSON string
    json_string = json.dumps(card_data)
    
    # Encrypt using RSA-OAEP with SHA-256
    encrypted = public_key.encrypt(
        json_string.encode(),
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    
    # Return base64-encoded string
    return base64.b64encode(encrypted).decode()

# Usage
public_key = """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----"""

card_data = {
    'card_number': '4111111111111111',
    'expiry_month': '12',
    'expiry_year': '2025',
    'cvv': '123',
    'cardholder_name': 'John Doe'
}

encrypted_data = encrypt_card_data(card_data, public_key)
print(encrypted_data)
# Output: "tbjH0nx6WaEkzHOjgw2crsusmVBuL8s+PxWF..."

Common Errors

Decryption Failed

{
  "status": "error",
  "message": "Failed to decrypt payment data",
  "code": "INVLDDATA"
}
Causes:
  • Using wrong public key (sandbox vs production)
  • Incorrect encryption algorithm (must be RSA-OAEP with SHA-256)
  • Malformed card data JSON
  • Base64 encoding error

Invalid Card Data

{
  "status": "error",
  "message": "Invalid card number",
  "code": "VALIDATIONERR"
}
Causes:
  • Card number fails Luhn check
  • Expired card
  • Invalid CVV length
  • Missing required fields