Card PIN Encryption and Decryption

This documentation shows how PIN is encrypted and Decrypted

The encryption and decryption of the PIN is done using an RSA key pair, where the public key encrypts the PIN and the private key performs the decryption. The code below is the implementation in JAVA and must be strictly adapted to ensure the correctness of the encrypted and decrypted values.

The encryption method should be used to encrypt the new and old card pin (if required) in the pin change request payload. This method is also used to encrypt the pin returned from a reissue pin request using the client's public key which would have been configured during client registration.

To decrypt the reissued pin, clients should implement the decryption method using the corresponding private key.

Implementation Prerequisites
JDK 8+
Import org.bouncycastle jar or Maven dependency compatible with your JDK.

public String encryptPin(String data) throws Exception{ return StringUtils.isBlank(data) ? "" : new String(Hex.encode(encrypt(Hex.encode(data.getBytes())))); } private byte[] encrypt(byte[] data) throws Exception { try { Cipher cipher = Cipher.getInstance(algorithm); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data); } catch (GeneralSecurityException e) { throw new Exception("Unable to encrypt data", e); } } public String decryptPin(String data) throws Exception{ return StringUtils.isBlank(data) ? "" : new String(Hex.decode(decrypt(Hex.decode(data)))); } private byte[] decrypt(byte[] data) throws Exception { try { Cipher cipher = Cipher.getInstance(algorithm); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(data); } catch (GeneralSecurityException e) { throw new Exception("Unable to decrypt data", e); } }

Database Sensitive Data Encryption and Decryption

This section details how a card production request is encrypted before it is saved on the database for future processing.

public String encrypt(String data) throws Exception { return StringUtils.isBlank(data) ? "" : encryptData(data, encryptionKey); } public String decrypt(String data) throws Exception{ return StringUtils.isBlank(data) ? "" : decryptData(data, encryptionKey); } public static String encryptData(String data, String issuerSecret) throws InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException { Security.addProvider(new BouncyCastleProvider()); Cipher cipher = Cipher.getInstance(SYMMETRIC_KEY_ALG, BouncyCastleProvider.PROVIDER_NAME); cipher.init(Cipher.ENCRYPT_MODE, getAESSecretKey(issuerSecret), getIvParamSpec()); byte[] encryptedData = cipher.doFinal(data.getBytes()); return new String(Base64.encode(encryptedData)); } public static String decryptData(String encryptedData, String issuerSecret) throws InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException { Security.addProvider(new BouncyCastleProvider()); Cipher cipher = Cipher.getInstance(SYMMETRIC_KEY_ALG, BouncyCastleProvider.PROVIDER_NAME); cipher.init(Cipher.DECRYPT_MODE, getAESSecretKey(issuerSecret), getIvParamSpec()); byte[] decodedData = Base64.decode(encryptedData); byte[] decryptedData = cipher.doFinal(decodedData); return new String(decryptedData, StandardCharsets.UTF_8); }

Decode PIN Block to PIN

HOW TO CALCULATE PIN FROM PIN BLOCK

REQUIREMENTS FOR COMPUTATION:
i. PIN BLOCK
ii. PAN

Format used: Format 0 (ISO-0)

METHOD:

  1. Prepare PAN - take 12 rightmost digits of the primary account number (excluding the check digit)
12345678910111213141516
0000PANPANPANPANPANPANPANPANPANPANPANPAN

  1. XOR both the Prepared PAN in step 1 above and the PIN Block
12345678910111213141516
12345678910111213141516
0LPPPPP/FP/FP/FP/FP/FP/FP/FP/FP/FP/F
XORXORXORXORXORXORXORXORXORXORXORXORXORXORXOR
0000PANPANPANPANPANPANPANPANPANPANPANPAN

  1. Parse the PIN - The first digit is zero, then the next digit L is length of the PIN, and then the next four digits P is PIN digit, after the pin F is padding value "F"
12345678910111213141516
0LPPPPP/FP/FP/FP/FP/FP/FP/FP/FP/FP/F

EXAMPLE


PAN: 43219876543210987
PIN BLOCK: 0412AC89ABCDEF67

XOR: 041234FFFFFFFFFF
PAD: N/A
Format: Format 0 (ISO-0)


Clear PIN: 1234