> ## Documentation Index
> Fetch the complete documentation index at: https://rain-sandbox-trial.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage a Card's PIN

> Set, encrypt, and retrieve a card's PIN securely using the PIN management API.

The PIN management API allows users to update and retrieve the PIN for their cards.

<Warning>
  #### Security best practices

  * Never store decrypted card details.
  * Only request card PIN details when absolutely necessary.
  * Always use the latest encryption libraries to maintain security.
</Warning>

This guide outlines the process of setting, encrypting, and retrieving a card’s PIN securely.

## Requirements

* User's `cardId` that you are setting the PIN for.

## Steps to set a card’s PIN

To securely update a card’s PIN, follow these steps:

<Steps>
  <Step title="User initiates a PIN update">
    Collect PIN from your user.
  </Step>

  <Step title="Ensure PIN meets security standards">
    <ul>
      <li>No simple sequences (e.g., `1234`, `0000`).</li>
      <li>No repeated numbers (e.g., `1111`, `2222`).</li>
      <li>Length must be between **4–12 digits**.</li>
    </ul>
  </Step>

  <Step title="Encrypt the PIN">
    Encrypt the PIN using the client session key before submitting it. (See sample below)
  </Step>

  <Step title="Submit the encrypted PIN to the API">
    Send a request to [set a PIN](/reference/cards/update-a-cards-pin) for a card.
    If the encrypted PIN is valid, the system updates the card's PIN.
  </Step>

  <Step title="Confirm the update">
    The API returns a success status with no body once the PIN is set.
  </Step>

  <Step title="(Optional) Retrieve the PIN">
    If the user needs to verify the updated PIN, call the [get a card's PIN](/reference/cards/get-a-cards-pin) endpoint.
  </Step>
</Steps>

## Encrypting and decrypting a PIN (TypeScript example)

Below is an example of how to encrypt a PIN before submission and decrypt it when retrieving it.

### Requirement: Generate a session Key and ID

<Info>
  Set the `pem` variable to Rain's [public RSA key for your environment](/docs/resource-sessionid-keys).
</Info>

```typescript generateSessionId.js theme={null}
import crypto from "crypto";
import { randomUUID } from "crypto";

// Generate session key and ID
const uuid = randomUUID().replace(/-/g, ""); // 32-character hex string
const sessionId = uuid;
const sessionIdBase64 = Buffer.from(sessionId, "hex").toString("base64");
const sessionIdBase64Buffer = Buffer.from(sessionIdBase64, "utf-8");

// Encrypt using RSA-OAEP padding with SHA-1 hash (matching browser implementation)
const sessionIdBase64BufferEncrypted = crypto.publicEncrypt(
   {
   key: pem,
   padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
   oaepHash: 'sha1',
   },
   sessionIdBase64Buffer,
);

const encryptedSessionId = sessionIdBase64BufferEncrypted.toString("base64");
// Use sessionId for encryption key, encryptedSessionId for the API header
```

### Step 2: Encrypt the PIN before submission

```typescript encryptPin.js theme={null}
function encryptPin(pin, sessionKey) {
   // Validate PIN length
   if (pin.length < 4 || pin.length > 12) {
    throw new Error("PIN must be between 4 and 12 digits");
   }

   // Format PIN as PIN block: 2[length_hex][PIN][F padding]
   // Example: PIN "6784" becomes "246784FFFFFFFFFF"
   const formattedPin = `2${pin.length.toString(16)}${pin}${'F'.repeat(14 - pin.length)}`;

   // Generate a random 16-byte IV
   const iv = crypto.randomBytes(16);

   // Use the first 16 bytes of the sessionId as the key for AES-128
   const key = Buffer.from(sessionId, 'hex').slice(0, 16);

   // Create cipher using AES-128-GCM
   const cipher = crypto.createCipheriv('aes-128-gcm', key, iv);

   // Encrypt the formatted PIN
   const encrypted = Buffer.concat([cipher.update(formattedPin, 'utf8'), cipher.final()]);
   const authTag = cipher.getAuthTag();

   // Combine the encrypted data and the auth tag
   const encryptedWithAuthTag = Buffer.concat([encrypted, authTag]);

   // Base64 encode for transmission
   const encryptedPin = encryptedWithAuthTag.toString('base64');
   const encodedIv = iv.toString('base64');

   return {
      encryptedPin,
      encodedIv
   };
}
```

### Decrypting the PIN when retrieved

```typescript decryptPin.js theme={null}
function decryptPin(base64Secret, base64Iv, sessionKey) {
   // base64Secret and base64Iv are the values retured from Get a card's PIN endpoint
   const secret = Buffer.from(base64Secret, "base64");
   const iv = Buffer.from(base64Iv, "base64");
   const secretKey = Buffer.from(sessionKey, "hex");

   const decipher = crypto.createDecipheriv("aes-128-gcm", secretKey, iv);
   decipher.setAutoPadding(false);

   const decrypted = decipher.update(secret).toString("utf-8");
   const retrievedPin = decrypted.substring(2, Number(decrypted[1]) + 2); // Extract PIN

   return {
      decrypted,
      retrievedPin
   }
}
```
