PCI Helper - RSA

RSA (Rivest–Shamir–Adleman) is a secure method to transmit sensitive cardholder data to TabaPay without storing or directly handling unencrypted Primary Account Numbers (PAN)s. RSA uses a public key to encrypt and a private key to decrypt. This ensures that even if intercepted, the card data cannot be read without the private key, maintaining PCI DSS compliance and protecting cardholder information in transit.

Why RSA?

RSA is the most widely used asymmetric algorithm. It ensures that unencrypted card details are never exposed during transmission and can help maintain PCI DSS compliance.

How RSA Works

The following examples display what to encrypt and how to handle the data.

Unencrypted Card Data Format

CardNumber|ExpirationDate|SecurityCode

  • No spaces
  • Pipe symbol (|) delimited
  • Expiration Date, Security Code optional

Examples

📘

Payload Should Be Compact

API examples are shown in a human-readable format for clarity. Actual API request bodies must use compact JSON.

CardNumber, ExpirationDate, SecurityCode

4000056655665556|202512|123

  • CardNumber is 4000056655665556
  • ExpirationDate is 202512
  • SecurityCode is 123

CardNumber, ExpirationDate, NO SecurityCode

4000056655665556|202512|

  • CardNumber is 4000056655665556
  • ExpirationDate is 202512
  • SecurityCode is blank

CardNumber, NO ExpirationDate, NO SecurityCode

4000056655665556||

  • CardNumber is 4000056655665556
  • ExpirationDate is blank
  • SecurityCode is blank

RSA Encryption

See the following JavaScript example for RSA encryption.

import forge from 'node-forge';
interface EncryptTabaPayCardDataParams {
  keyData: string; // public key data for TabaPay
  cardNumber: string; // user input debit card number
  expDate: string; // user input expiration date for debit card
}
export const base64EncodeUrl = (s: string) => {
  return s
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '');
};
export const base64DecodeUrl = (s: string) => {
  const str = `${s}===`.slice(0, s.length + (s.length % 4));
  return str.replace(/-/g, '+').replace(/_/g, '/');
};
export const formatPemPublicKey = (str: string) => {
  return `-----BEGIN PUBLIC KEY-----\r\n${str}\r\n-----END PUBLIC KEY-----\r\n`;
};
/**
 * Encrypts card data into base 64 URL format for TabaPay
 * @param EncryptTabaPayCardDataParams TabaPay public key data and user's debit
 * card number & expiration date
 */
export const encryptTabaPayCardData = ({
  keyData,
  cardNumber,
  expDate,
}: EncryptTabaPayCardDataParams): string => {
  // decode the base 64 url encoded key data
  const decodedKey = base64DecodeUrl(keyData);
  // format the decoded key using PEM format
  const pemKey = formatPemPublicKey(decodedKey);
  // use forge to get public key
  const publicKey = forge.pki.publicKeyFromPem(pemKey);
  const cardData = `${cardNumber}|${expDate}|`;
  // encrypt the card data
  const encrypted = publicKey.encrypt(cardData, 'RSA-OAEP', {
    md: forge.md.sha256.create(),
    mgf1: {
      md: forge.md.sha256.create(),
    },
  });
  // encode encrypted data to base 64 url format
  const encryptedBase64 = forge.util.encode64(encrypted);
  return base64EncodeUrl(encryptedBase64);
};

RSA FAQs

1. Using Encrypted Data in the TabaPay API Calls doesn't seem to be working?

Make sure you are using RSA with the Transformation of RSA/ECB/OAEPWithSHA-256AndMGF1Padding and the language you are using supports the correct (common usage) implementation of that transform.

2. Receiving a SC=500?

If you pass in an Encrypted Data that was encrypted incorrectly, you will get a SC=500.

3. What languages (and libraries, if any) work (or are tested)?

The following languages and libraries have been verified to work with TabaPay's RSA encryption:

  • Java with a slight tweak using the built in RSA encryption
  • Go using the built in RSA encryption
  • .NET
    and other applications (or libraries):
  • OpenSSL
4. Can I have more than 2 active keys?

We have found 2 active keys is plenty for production environments. The key you are using is just a Public Key, so security shouldn't be an issue.

5. Since we can only have 2 active Keys, can the Key expire in more than 1 year?

No, due to PCI Compliance.

6. Is it possible to use RSA encryption for a web browser?

No, due to PCI Compliance. RSA is only allowed for mobile.

Recipe