Skip to content

Latest commit

 

History

History
259 lines (192 loc) · 9.23 KB

File metadata and controls

259 lines (192 loc) · 9.23 KB

8. Security and Encryption

8.1. PIN block formats

PIN (Personal Identification Number) encryption is a critical security measure in financial transactions. PIN blocks are used to securely transmit PINs across networks. There are several PIN block formats, but we'll focus on the most common ones:

8.1.1. ISO Format 0 (Zero)

This is the most widely used format.

  • Structure: 0 || PIN length || PIN || Padding
  • The PIN is left-justified and padded with 'F'
  • Example: For PIN "1234", the block would be "041234FFFFFFFFFF"

8.1.2. ISO Format 1

This format incorporates the PAN (Primary Account Number) for added security.

  • Structure: 1 || PIN length || PIN ⊕ PAN || Padding
  • The PIN is XORed with the rightmost 12 digits of the PAN
  • Example: For PIN "1234" and PAN "1234567890123456", the block might be "141234567890FFFF"

8.1.3. ISO Format 3

This format is similar to Format 0 but uses a different padding method.

  • Structure: 3 || PIN length || PIN || Random padding
  • The PIN is left-justified and padded with random digits
  • Example: For PIN "1234", the block could be "341234987654321"

Let's implement a PIN block generator for these formats using jPOS:

import org.jpos.iso.ISOUtil;
import org.jpos.security.SMException;

public class PINBlockGenerator {

    public static String generateFormat0(String pin) throws SMException {
        if (pin.length() < 4 || pin.length() > 12) {
            throw new SMException("PIN must be between 4 and 12 digits");
        }
        StringBuilder block = new StringBuilder();
        block.append("0");
        block.append(String.format("%01d", pin.length()));
        block.append(pin);
        while (block.length() < 16) {
            block.append("F");
        }
        return block.toString();
    }

    public static String generateFormat1(String pin, String pan) throws SMException {
        if (pin.length() < 4 || pin.length() > 12) {
            throw new SMException("PIN must be between 4 and 12 digits");
        }
        if (pan.length() < 13 || pan.length() > 19) {
            throw new SMException("PAN must be between 13 and 19 digits");
        }
        StringBuilder block = new StringBuilder();
        block.append("1");
        block.append(String.format("%01d", pin.length()));
        
        String panPart = pan.substring(pan.length() - 13, pan.length() - 1);
        String pinPadded = String.format("%-12s", pin).replace(' ', 'F');
        
        byte[] xoredPart = ISOUtil.xor(pinPadded.getBytes(), panPart.getBytes());
        block.append(ISOUtil.hexString(xoredPart));
        
        return block.toString();
    }

    public static String generateFormat3(String pin) throws SMException {
        if (pin.length() < 4 || pin.length() > 12) {
            throw new SMException("PIN must be between 4 and 12 digits");
        }
        StringBuilder block = new StringBuilder();
        block.append("3");
        block.append(String.format("%01d", pin.length()));
        block.append(pin);
        while (block.length() < 16) {
            block.append(String.valueOf((int) (Math.random() * 10)));
        }
        return block.toString();
    }
}

8.2. Key management

Key management is crucial for maintaining the security of encrypted communications. There are typically three types of keys used in ISO-8583 implementations:

8.2.1. Master keys

  • Also known as Key Encryption Keys (KEKs)
  • Used to encrypt other keys
  • Typically distributed manually or through a secure out-of-band method

8.2.2. Session keys

  • Temporary keys used for a single session or a limited time
  • Generated and exchanged using the master key
  • Provide forward secrecy, as compromising one session key doesn't compromise past or future sessions

8.2.3. Working keys

  • Used for actual data encryption (e.g., PIN encryption)
  • Often derived from session keys

Let's implement a basic key management system using jPOS:

import org.jpos.security.SMAdapter;
import org.jpos.security.SecureKeyStore;
import org.jpos.security.SimpleKeyFile;
import org.jpos.security.jceadapter.JCESecurityModule;
import org.jpos.util.Logger;
import org.jpos.util.SimpleLogListener;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;

public class KeyManager {
    private final SMAdapter sm;
    private final SecureKeyStore ks;

    public KeyManager() throws Exception {
        Logger logger = new Logger();
        logger.addListener(new SimpleLogListener(System.out));

        ks = new SimpleKeyFile("keystore.ks");
        sm = new JCESecurityModule("jce", logger);
    }

    public SecretKey generateMasterKey() throws NoSuchAlgorithmException {
        KeyGenerator keyGen = KeyGenerator.getInstance("DES");
        keyGen.init(168); // Use Triple DES (112-bit) key
        return keyGen.generateKey();
    }

    public SecretKey generateSessionKey() throws NoSuchAlgorithmException {
        KeyGenerator keyGen = KeyGenerator.getInstance("DES");
        keyGen.init(56); // Use single DES key for session
        return keyGen.generateKey();
    }

    public byte[] encryptSessionKey(SecretKey masterKey, SecretKey sessionKey) throws Exception {
        return sm.encryptKey(masterKey, sessionKey);
    }

    public SecretKey decryptSessionKey(SecretKey masterKey, byte[] encryptedSessionKey) throws Exception {
        return sm.decryptKey(masterKey, encryptedSessionKey, "DES");
    }

    public void storeMasterKey(String alias, SecretKey masterKey) throws Exception {
        ks.setKey(alias, masterKey);
    }

    public SecretKey retrieveMasterKey(String alias) throws Exception {
        return (SecretKey) ks.getKey(alias);
    }
}

8.3. Secure messaging

Secure messaging ensures the integrity and confidentiality of ISO-8583 messages.

8.3.1. MAC (Message Authentication Code)

MAC is used to verify the integrity of the message and authenticate the sender.

Let's implement MAC generation and verification:

import org.jpos.iso.ISOUtil;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class MACGenerator {

    public static byte[] generateMAC(byte[] message, SecretKey key) throws NoSuchAlgorithmException, InvalidKeyException {
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(key);
        return mac.doFinal(message);
    }

    public static boolean verifyMAC(byte[] message, byte[] receivedMAC, SecretKey key) throws NoSuchAlgorithmException, InvalidKeyException {
        byte[] calculatedMAC = generateMAC(message, key);
        return ISOUtil.equals(calculatedMAC, receivedMAC);
    }
}

8.3.2. DUKPT (Derived Unique Key Per Transaction)

DUKPT is a key management scheme that generates a unique key for each transaction, enhancing security.

Here's a basic implementation of DUKPT key derivation:

import org.jpos.security.SMException;
import org.jpos.security.jceadapter.JCEHandler;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class DUKPTKeyDerivation {
    private static final byte[] KSN_MASK = ISOUtil.hex2byte("FFFFFFFFFFFFFFE00000");
    private static final byte[] DATA_MASK = ISOUtil.hex2byte("0000000000FF00000000000000000000");

    public static SecretKey deriveKey(SecretKey bdk, byte[] ksn) throws SMException, NoSuchAlgorithmException, InvalidKeyException {
        JCEHandler jceHandler = new JCEHandler();
        
        // Initial PIN Encryption Key (IPEK)
        byte[] ipek = jceHandler.encryptDES(bdk, ksn);
        
        byte[] derivedKey = ipek;
        byte[] counter = new byte[3];
        System.arraycopy(ksn, 7, counter, 0, 3);
        
        for (int i = 0; i < 21; i++) {
            if ((counter[i / 8] & (1 << (i % 8))) != 0) {
                byte[] ksnRegister = ISOUtil.xor(ksn, KSN_MASK);
                ksnRegister[7] &= 0xE0;
                ksnRegister[8] = 0x00;
                ksnRegister[9] = 0x00;
                
                byte[] data = ISOUtil.xor(derivedKey, DATA_MASK);
                byte[] leftKey = new byte[8];
                byte[] rightKey = new byte[8];
                System.arraycopy(derivedKey, 0, leftKey, 0, 8);
                System.arraycopy(derivedKey, 8, rightKey, 0, 8);
                
                byte[] leftData = jceHandler.encryptDES(new SecretKeySpec(leftKey, "DES"), data);
                byte[] rightData = ISOUtil.xor(leftData, rightKey);
                
                System.arraycopy(leftData, 0, derivedKey, 0, 8);
                System.arraycopy(rightData, 0, derivedKey, 8, 8);
                
                ksnRegister[i / 8] |= (1 << (i % 8));
            }
        }
        
        return new SecretKeySpec(derivedKey, "DES");
    }
}

This implementation covers the basics of security and encryption in ISO-8583 using jPOS. In a real-world scenario, you would need to integrate these components into your larger application architecture, ensuring proper key storage, rotation, and management practices.

Remember that security is critical in financial applications, and it's always recommended to have security experts review your implementation and conduct thorough security audits.