PAN encryption for 3DS authentication
3-D Secure (3DS) authentication is a card-payment security protocol that adds an extra layer of verification for online card-not-present transactions before authorization. This protocol confirms that the person making the payment is the legitimate cardholder and helps to reduce fraud.
The Send pre-authentication info endpoint sends information to the client's anti-fraud validator to evaluate. The Pismo platform calls the validator's webhook and gets a response before sending a response to the caller.
Pismo provides the encrypt/decrypt keys for the hashed Primary Account Number (PAN). Pismo's PAN encryption uses RSA with Optimal Asymmetric Encryption Padding (OAEP) and Secure Hash Algorithm3, 256-bit (SHA3-256) hashing to securely encrypt sensitive data. The following describes the steps to encrypt the PAN to use with the Send pre-authentication info endpoint.
Implementation steps
Prerequisites
- RSA public key (2048-bit or 4096-bit recommended)
- Support for SHA3-256 hashtag algorithm
Step 1: Obtain the public key
Open an internal service desk (ISD) ticket to request the RSA public key. You must provide the following information:
- The environment you are using: test or production
- Org ID
Please note that the process to generate and store the private key and to complete the client setup on the 3DS API involves multiple teams and can take some time.
3DS providers
If you are a 3DS provider, you cannot open an ISD ticket. You must contact your client and ask them to request the key and provide it to you.
If you serve more than one issuer with Pismo, each of them will have its own key for PAN encryption.
Step 2: Configure the cipher
Set up the RSA encryption with these specific parameters:
- Algorithm: RSA
- Padding: OAEP
- Hash function: SHA3-256
- Mask Generation Function (MFG): MFG1 with SHA3-256
Step 3: Encrypt the data
- Convert your sensitive data (PAN) to bytes.
- Use the public key to encrypt the data.
The encryption will produce a byte array.
Step 4: Encode the result
Encode the encrypted bytes using Base64 Standard Encoding.
This produces a string safe for transmission in the JSON/HTTP.
Complete examples
Java implementation:
public String encryptPAN(PublicKey publicKey, String pan) throws Exception {
// Step 1: Initialize cipher
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA3-256AndMGF1Padding");
// Step 2: Configure OAEP parameters
OAEPParameterSpec oaepParams = new OAEPParameterSpec(
"SHA3-256", // Hash algorithm
"MGF1", // Mask generation function
MGF1ParameterSpec.SHA3_256, // MGF hash
PSource.PSpecified.DEFAULT // No label
);
// Step 3: Initialize for encryption
cipher.init(Cipher.ENCRYPT_MODE, publicKey, oaepParams, new SecureRandom());
// Step 4: Encrypt
byte[] encryptedBytes = cipher.doFinal(pan.getBytes());
// Step 5: Encode to Base64
return Base64.getEncoder().encodeToString(encryptedBytes);
}Note: If SHA3-256 is not available, add Bouncy Castle dependency.
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.78</version>
</dependency>
Go implementation
func encryptPAN(publicKey *rsa.PublicKey, pan string) (string, error) {
// Step 1: Encrypt using OAEP with SHA3-256
encryptedBytes, err := rsa.EncryptOAEP(
sha3.New256(), // Hash function
rand.Reader, // Random source
publicKey, // Public key
[]byte(pan), // Data to encrypt
nil, // Optional label (not used)
)
if err != nil {
return "", err
}
// Step 2: Encode to Base64
return base64.StdEncoding.EncodeToString(encryptedBytes), nil
}Test your implementation
- Test with sample data. Use a known PAN value.
- Verify Base64 output. Ensure the result is valid Base64.
- Complete a length check. Encrypted output should match your key size (for example, 256 bytes for 2048-bit key).
- Complete an integration test. Send the encrypted value to the API endpoint.
- If you encounter any errors, reach out to your Pismo representative.
Updated about 4 hours ago