> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nadcab.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Card data encryption

> Receive full card numbers and CVVs encrypted to your RSA key.

Full card details are never returned in plain text. Once you register an RSA public key, [Get card secrets](/api-reference/cards/get-card-secrets) returns an encrypted `pan` field that only your private key can decrypt.

## 1. Generate a key pair

Generate the key pair on your own server. Never generate or paste your private key into a third-party website.

```bash theme={null}
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:1024 -out card_private.pem
openssl rsa -in card_private.pem -pubout -out card_public.pem
```

## 2. Register the public key

Send the contents of `card_public.pem` to [Set public key](/api-reference/api-settings/set-public-key):

```bash theme={null}
curl https://cc.nadcab.com/api/v1/account/setPubkey \
  -H "Authorization: Bearer $NADCAB_API_KEY" \
  --data-urlencode "pubkey@card_public.pem"
```

## 3. Decrypt card data

[Get card secrets](/api-reference/cards/get-card-secrets) returns masked `card_no`, `cvv` and `expire_date`, plus the encrypted `pan`:

```json theme={null}
{
  "code": 200,
  "msg": "success",
  "data": {
    "card_no": "493728******6685",
    "cvv": "***",
    "expire_date": "**/****",
    "pan": "U00tt5dzeV2bK2veQ8U1C+KBE2dCqQdfm3ep106l..."
  }
}
```

`pan` is Base64 and encrypted with `RSA/NONE/OAEPWithSHA1AndMGF1Padding`. Decrypt it with your private key:

<CodeGroup>
  ```javascript Node.js theme={null}
  import { constants, privateDecrypt } from "node:crypto";
  import { readFileSync } from "node:fs";

  const privateKey = readFileSync("card_private.pem", "utf8");

  export function decryptPan(pan) {
    return privateDecrypt(
      { key: privateKey, padding: constants.RSA_PKCS1_OAEP_PADDING, oaepHash: "sha1" },
      Buffer.from(pan, "base64")
    ).toString("utf8");
  }
  ```

  ```python Python theme={null}
  import base64
  from cryptography.hazmat.primitives import hashes, serialization
  from cryptography.hazmat.primitives.asymmetric import padding

  with open("card_private.pem", "rb") as f:
      private_key = serialization.load_pem_private_key(f.read(), password=None)

  def decrypt_pan(pan: str) -> str:
      return private_key.decrypt(
          base64.b64decode(pan),
          padding.OAEP(mgf=padding.MGF1(hashes.SHA1()), algorithm=hashes.SHA1(), label=None),
      ).decode("utf-8")
  ```
</CodeGroup>

<Warning>
  Decrypted card data is sensitive. Show it only to the cardholder, never log it, and follow PCI DSS rules if you store it.
</Warning>
