m2pfintech
Integration Guide

Gateway Encryption

RSA + AES envelope encryption for sensitive operations like PIN management and card data retrieval.

For operations involving sensitive card data (PIN set, full card number retrieval), the M2P Platform requires envelope encryption using RSA + AES.


Encryption Flow


How It Works

StepActionAlgorithm
1Generate a random AES-256 key and initialization vector (IV)AES-256
2Encrypt the JSON request payload using AES-256-CBCAES-256-CBC
3Encrypt the AES key using M2P's RSA public keyRSA PKCS1
4Send the encrypted payload, encrypted key, and IV to the gatewayHTTPS
5Gateway decrypts the AES key using its RSA private keyRSA PKCS1
6Gateway decrypts the payload and processes the requestAES-256-CBC

Implementation

const crypto = require('crypto');

function encryptForGateway(payload, m2pRsaPublicKey) {
  // Step 1: Generate random AES-256 key and IV
  const aesKey = crypto.randomBytes(32);
  const iv = crypto.randomBytes(16);

  // Step 2: Encrypt payload with AES-256-CBC
  const cipher = crypto.createCipheriv('aes-256-cbc', aesKey, iv);
  let encryptedData = cipher.update(
    JSON.stringify(payload), 'utf8', 'base64'
  );
  encryptedData += cipher.final('base64');

  // Step 3: Encrypt AES key with RSA public key
  const encryptedKey = crypto.publicEncrypt(
    {
      key: m2pRsaPublicKey,
      padding: crypto.constants.RSA_PKCS1_PADDING
    },
    aesKey
  ).toString('base64');

  // Step 4: Return the encrypted bundle
  return {
    encryptedData,
    encryptedKey,
    iv: iv.toString('base64')
  };
}
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
import java.util.Base64;

public class GatewayEncryption {

    public static Map<String, String> encrypt(
        String payload, PublicKey m2pRsaPublicKey
    ) throws Exception {
        // Step 1: Generate random AES-256 key and IV
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(256);
        SecretKey aesKey = keyGen.generateKey();
        byte[] iv = new byte[16];
        new SecureRandom().nextBytes(iv);

        // Step 2: Encrypt payload with AES-256-CBC
        Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        aesCipher.init(Cipher.ENCRYPT_MODE, aesKey,
            new IvParameterSpec(iv));
        byte[] encryptedData = aesCipher.doFinal(
            payload.getBytes(StandardCharsets.UTF_8));

        // Step 3: Encrypt AES key with RSA public key
        Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        rsaCipher.init(Cipher.ENCRYPT_MODE, m2pRsaPublicKey);
        byte[] encryptedKey = rsaCipher.doFinal(aesKey.getEncoded());

        // Step 4: Return the encrypted bundle
        return Map.of(
            "encryptedData", Base64.getEncoder()
                .encodeToString(encryptedData),
            "encryptedKey", Base64.getEncoder()
                .encodeToString(encryptedKey),
            "iv", Base64.getEncoder()
                .encodeToString(iv)
        );
    }
}

When Encryption Is Required

OperationEncryption RequiredReason
Set PINYesPIN must never be transmitted in plaintext
Change PINYesPIN must never be transmitted in plaintext
Full Card Number RetrievalYesFull PAN is sensitive cardholder data
Encrypted Card Data (Tokenization)YesCard data for Apple Pay / Google Pay provisioning
Standard API CallsNoJWT + HTTPS provides sufficient security

Never transmit card PINs or full card numbers without gateway encryption. This is a PCI-DSS compliance requirement.

On this page