> ## 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.

# Encryption

> Encrypt payment data

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:

```json theme={null}
{
  "card_number": "4111111111111111",
  "expiry_month": "12",
  "expiry_year": "2025",
  "cvv": "123",
  "cardholder_name": "John Doe"
}
```

## Implementation Examples

**Node.js Example**

```javascript theme={null}
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)**

```python theme={null}
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

```json theme={null}
{
  "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

```json theme={null}
{
  "status": "error",
  "message": "Invalid card number",
  "code": "VALIDATIONERR"
}
```

**Causes**:

* Card number fails Luhn check
* Expired card
* Invalid CVV length
* Missing required fields
