Saturday, March 16, 2019

DUKPT in JAVA using jPOS


Any encryption algorithm is only as secure as its keys.The strongest algorithm is useless if the keys used to encrypt the data with the algorithm are not secure.This is like locking your door with the biggest and strongest lock, but if you hid the key under the doormat, the lock itself is useless. When we talk about encryption, we also need to keep in mind that the data has to be decrypted at the other end.Typically, the weakest link in any encryption scheme is the sharing of the keys between the encrypting and decrypting parties. DUKPT is an attempt to ensure that both the parties can encrypt and decrypt data without having to pass the encryption/decryption keys around.

One of the most common E2EE solutions used by merchants is derived unique key per transaction (DUKPT) also known as “duck putt”.  DUKPT is commonly used in the convenience store and gas station industries to encrypt sensitive authentication data (SAD) from the gas pump to the merchant or processor.



DUKPT uses the 56-bit data encryption standard (DES) encryption or triple DES (3DES) algorithms.
While DES and 3DES 56-bit and 112-bit are no longer considered secure, because DUKPT uses a unique key for every transaction, it means that every transaction has to be individually broken to gain access to the data. While using the cloud could be leveraged to perform this rapidly, it would be too costly an effort for the data retrieved.  As a result, DUKPT using DES is still technically considered a secure method of encryption although it is never recommended for use.  3DES and AES are now the more commonly implemented algorithms with AES being the preferred solution if supported by the POI. 3DES encryption is a common algorithm implemented by well known libraries like BouncyCastle and Java JCE.

DUKPT is not itself an encryption standard; rather it is a key management technique. The features of the DUKPT scheme are:
  • Enable both originating and receiving parties to be in agreement as to the key being used for a given transaction,
  •  Each transaction will have a distinct key from all other transactions, except by coincidence,
  • If a present derived key is compromised, past and future keys (and thus the transactional data encrypted under them) remain uncompromised,
  • Each device generates a different key sequence,
  • Originators and receivers of encrypted messages do not have to perform an interactive key-agreement protocol beforehand.

Derived Key Generation Process



 The following procedure is used for device initialization and encryption.
  1. First: A key is irreversibly derived from the BDK (within a TRSM). This is known as the Initial PIN Encryption Key (IPEK).
  2. Second: The IPEK is then injected into the devices, so any compromise of that key compromises only the device, not the BDK
  3. Third: This IPEK creates yet another set of keys (inside the device) irreversibly derived from it (nominally called the Future Keys)
  4. Fourth: Afterwards the IPEK is then immediately discarded. (NOTE: This step contradicts "Session Keys" section where it indicates that only 21 "Future Keys" are generated.) The IPEK must be retained by the terminal in order generate the next batch of 21 Future Keys.
  5. Fifth: Future Keys are used to encrypt transactions in the DUKPT process.
Upon detection of compromise the device itself a new IPEK is derived inside the TRSM and the Derived Key Generation Process is restarted.



Keys used in DUKPT


BDK : Base Derivation Key: 32 hexadecimal character {0-9, A-F} key, which is randomly generated
KSN : Key Serial Number: 20 hexadecimal characters comprised of three unique parts: Key Set Identifier, Device Identification,and Transaction Counter
  • KSI : Key Set Identifier: First 10 characters of KSN, which serves as a BDK identifier in payment application systems
  • DID : Device Identification: Next 5 characters of KSN, which enables 524,287 individual POS devices to be injected with a single key
  • CTR : Transaction Counter: Last 5 characters of KSN, enabling 1, 048, 575 transactions to occur from each POS device
IPEK : Initial PIN Encryption Key: Cryptographically combining the BDK and KSN will yield the IPEK, which is the key actually injected into a POS terminal. This key is then utilized to derive future “Transaction Keys” – this same sequence can be used for PAN encryption utilizing an interoperable key exchange format
If BDK is compromised then all devices and all transactions are similarly compromised.Generally the security parameters in the devices are ‘distant’ from the sensitive BDK, and if the device is compromised, other devices are not implicitly compromised.

This is mitigated by the fact that there are only two parties that know the BDK:
  • The recipient of the encrypted messages (typically a merchant acquirer)
  • The party which initializes the encryption devices (typically the manufacturer of the device).
On the receiving side there is no state information retained; only the BDK is persistent across processing operations. The BDK is usually stored inside a Tamper-Resistant security module (TRSM), or Hardware Security Module (HSM).


What is DUKPT

 

  • Derived Unique Key Per Transaction (DUKPT) is a key management scheme. It uses one time encryption keys that are derived from a secret master key that is shared by the entity (or device) that encrypts and the entity (or device) that decrypts the data.
  • This technique involves the use of Base Derivation Key (BDK) and Key Serial Number (KSN).
    On each transaction, the PIN pad generates a new encryption keys that are derived from a secret BDK and a non-secret KSN. It encrypts the PIN with this key, and then forwards both the encrypted PIN and the key serial number to the acquirer.
  • The card reader utilizes DUKPT(derived unique key per transaction) scheme and 3DES encryption.The client device uses the IPEK to come up with a table of Future Keys and then discards the IPEK. So the client device now has it's original serial number, a counter (combined are the KSN) and a list of Future Keys.To encrypt the data, the client device grabs the first Future Key from the list and uses that as the encryption key. It then sends the encrypted data and it's KSN (which contains the counter) to the server.
  • On the server end, the server knows it's own secret (the BDK) and now has the clent device's KSN. The server uses those two keys to produce the IPEK .With the IPEK the server can recreate the table of Future Keys and knowing the counter provided by the client (the last 5 characters of the KSN) it knows which key from the table to use.
  • DUKPT allows the processing of the encryption to be moved away from the devices that hold the shared secret. The encryption is done with a derived key, which is not re-used after the transaction. 

 

How DUKPT Works

 

  • DUKPT uses one time keys that are generated for every transaction and then discarded.The advantage is that if one of these keys is compromised, only one transaction will be compromised.
  • With DUKPT, the originating (say, a Pin Entry Device or PED) and the receiving (processor, gateway, etc) parties share a key. This key is not actually used for encryption. Instead, another one time key that is derived from this master key is used for encrypting and decrypting the data. It is important to note that the master key should not be recoverable from the derived one time key.
  • To decrypt data, the receiving end has to know which master key was used to generate the one time key. This means that the receiving end has to store and keep track of a master key for each device.This can be a lot of work for someone that supports a lot of devices. A better way is required to deal with this.
  • This is how it works in real-life: The receiver has a master key called the Base Derivation Key (BDK). The BDK is supposed to be secret and will never be shared with anyone. This key is used to generate keys called the Initial Pin Encryption Key (IPEK). From this a set of keys called Future Keys is generated and the IPEK discarded.
  • Each of the Future keys is embedded into a PED by the device manufacturer, with whom these are shared. This additional derivation step means that the receiver does not have to keep track of each and every key that goes into the PEDs. They can be re-generated when required.
  • The receiver shares the Future keys with the PED manufacturer, who embeds one key into each PED.If one of these keys is compromised, the PED can be rekeyed with a new Future key that is derived from the BDK, since the BDK is still safe.

 Encryption and Decryption Process In DUKPT 

 

  • When data needs to be sent from the PED to the receiver, the Future key within that device is used to generate a one time key and then this key is used with an encryption algorithm to encrypt the data. This data is then sent to the receiver along with the Key Serial Number (KSN) which consists of the Device ID and the device transaction counter.
  • Based on the KSN, the receiver then generates the IPEK and from that generates the Future Key thatwas used by the device and then the actual key that was used to encrypt the data. With this key,the receiver will be able to decrypt the data.

Origination/Encryption

On the originating (encrypting) end, the system works as follows:
  • A transaction is initiated which involves data to be encrypted. The typical case is a customer's PIN.
  • A key is retrieved from the set of “Future Keys”
  • This is used to encrypt the message, creating a cryptogram.
  • An identifier known as the “Key Serial Number” (KSN) is returned from the encrypting device, along with the cryptogram. The KSN is formed from the device’s unique identifier, and an internal transaction counter.
  • The (cryptogram, KSN) pair is forwarded on to the intended recipient, typically the merchant acquirer, where it is decrypted and processed further.
  • Internally, the device does the following:
                a. Increments the transaction count (using an internal counter)
                b. Invalidates the key just used, and
                c. If necessary generates more future keys

Receiving/Decryption

On the receiving (decrypting) end, the system works as follows:
  • The (cryptogram, KSN) pair are received.
  • The appropriate BDK (if the system has more than one) is located.
  • The receiving system first regenerates the IPEK, and then goes through a process similar to that used on the originating system to arrive at the same encrypting key that was used (the session key). The Key Serial Number (KSN) provides the information needed to do this.
  • The cryptogram is decrypted with session key.
  • Any further processing is done. For merchant acquirers, this usually means encrypting under another key to forward on to a switch (doing a “translate”), but for certain closed-loop operations may involve directly processing the data, such as verifying the PIN.

DUKPT in Java Using jPOS :

  • Each Hardware Security Module (HSM) has its own Master Key and can be called an LMK or KSK  (Key Storage Key).
  • Every key you generate will be encrypted under this LMK. In real life you will never know the clear value of the LMK, the HSM will store it on a chip card. 
  • The JPOS API has very good support and can help you generate keys, encrypt, decrypt, form PIN blocks and translate PIN blocks

Java Dependency Libraries :

  • bcprov-jdk15on-1.58.jar
  • jpos-2.1.1.jar
  • commons-cli-1.4.jar
  • jdom2-2.0.6.jar
  • javatuples-1.2.jar

Step 1 : Start jPOS Command Line Interface .


Use --cli command line option that starts the jPOS command line interface .You  can start the command line interface in two ways :

1. By running Q2 using "--cli" as argument in java code
import org.jpos.q2.Q2;

public class Q2CommandLineInterface {
  public static void main(String[] args) {
    try { 
   Q2 q2 = new Q2(new String[] { "--cli" });
      q2.start();
    }catch (Exception localException) {}
  }
}

2. By calling bin/q2 --cli .
$ bin/q2 --cli
q2>

You should see a prompt like this



Step 2 : Generate LMK file using smconsole

$ q2> smconsole -lmk <lmk file path + lmk file name> -rebuildlmk
This will create the LMK file, on provided lmk file path



/tmp/dukpt-lmk

LMK0x01=7F3E2F01893DE50B7A3BBA34EFF80D317F3E2F01893DE50B
LMK0x00=F1FB3E37F176E683913B4F86385B4A01F1FB3E37F176E683
LMK0x09=5152DA52D5BF1A26D9F826E307973BB05152DA52D5BF1A26
LMK0x08=A1B6DAAEA78575D0D691893780F4DF91A1B6DAAEA78575D0
LMK0x0e=4AD3C4299162E3F12FF2BCCE97B00E7F4AD3C4299162E3F1
LMK0x07=DF132FFB32EF23DA67F8C229AD08BC38DF132FFB32EF23DA
LMK0x0d=F480F42349A23D0D6EC4D6018A76E975F480F42349A23D0D
LMK0x06=B3C2EAAE15D629E56DEA07F12CD9018FB3C2EAAE15D629E5
LMK0x0c=F89D45F270FEFE97B5E38558BC084F62F89D45F270FEFE97
LMK0x05=1A4AABA845EAF72A9102D362525710F11A4AABA845EAF72A
LMK0x0b=DC076BA7462CC746AD830885A1925D40DC076BA7462CC746
LMK0x04=61C15DFD2C700104F1B5981F38F4371A61C15DFD2C700104
LMK0x0a=6D5B525E4FA4944001AE13B986AE7AC76D5B525E4FA49440
LMK0x03=2CB0079E328C45FD9B584F6773083BC82CB0079E328C45FD
LMK0x02=C8DF2FEF08FDA126CB5D2C52FB8C1920C8DF2FEF08FDA126

Step 3 : Import the BDK using the 'smconsole' command that would encrypt it under the LMK. 


The Encrypted BDK will  be used at the time of Decryption and You will get encrypted bdk and the check value.
$ q2> smconsole –lmk <lmk _file_name> FK 128 BDK <BDK1> <BDK2> <BDK3>

Note 1:
If you have only one BDK ,  BDK2 and BDK3 are not available then fill it with Zeros(0).
Example : Original bdk 0123456789ABCDEFFEDCBA9876543210):
$ q2> smconsole –lmk <lmk _file_name> FK 128 BDK 0123456789ABCDEFFEDCBA9876543210 00000000000000000000000000000000 00000000000000000000000000000000

Note 2:
If you have two bdk,then run below command,
Example : Original bdk 0123456789ABCDEFFEDCBA9876543210 and 0123456789ABCDEFFEDCBA9876543210
$ q2> smconsole –lmk <lmk _file_name> FK 128 BDK 0123456789ABCDEFFEDCBA9876543210 0123456789ABCDEFFEDCBA9876543210 00000000000000000000000000000000


/tmp/dukpt-bdk
 
dukpt-bdk.key=26FB71EA0C9CBBA1D51CA00CFFA36374
dukpt-bdk.checkvalue=08D7B4
dukpt-bdk.length=128
dukpt-bdk.type=BDK
dukpt-bdk.class=org.jpos.security.SecureDESKey


 Step 4 : Swiped credit card using ID Tech card reader and decrypt the card data in java jPOS.



DukptAdapter.java
package com.java2depth.dukpt;

import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jpos.core.ConfigurationException;
import org.jpos.iso.ISOUtil;
import org.jpos.security.KeySerialNumber;
import org.jpos.security.SMException;
import org.jpos.security.SecureDESKey;
import org.jpos.security.SecureKeyStore;
import org.jpos.security.SecureKeyStore.SecureKeyStoreException;
import org.jpos.security.SimpleKeyFile;

public class DukptAdapter {
 
 SSM sm;
    SecureKeyStore ks;
    
   private void initSM () throws ConfigurationException, SMException {
    sm = new SSM("/tmp/dukpt-lmk","com.sun.crypto.provider.SunJCE");
    }
    
    private void initKS () throws Exception {
     
        ks = new SimpleKeyFile ("/tmp/dukpt-bdk");
    }
 
 private  SecureDESKey getBDK(String keyName) throws SecureKeyStoreException{
     SecureDESKey bdk = (SecureDESKey) ks.getKey (keyName);
     return bdk;
 }
 
 
    private KeySerialNumber getKSN(String ksn) throws Exception{
     if(ksn!=null && ksn.length()!=20)
      throw new Exception("Invalid KSN Size");
     String baseKeyID=ksn.substring(0, 10);
     String deviceID=ksn.substring(10, 15);
     String transacionCounter=ksn.substring(15, 20);
     KeySerialNumber ksnDecrypted = new KeySerialNumber(baseKeyID,deviceID,transacionCounter);
     return ksnDecrypted;
    }
    
    private  byte[] getDerivedKey(KeySerialNumber ksn,SecureDESKey bdk) throws SecureKeyStoreException, SMException{
     byte[] derivedKey = sm.calculateDerivedKey(ksn, bdk, true);
     return derivedKey;
 }
    
    private  byte[] decrypt(byte[] dataInByte, byte[] derivedKey)throws Exception {
  Security.addProvider(new BouncyCastleProvider());
  SecretKey keySpec = new SecretKeySpec(derivedKey, "DESede");
  Cipher decrypter = Cipher.getInstance("DESede/CBC/Nopadding", "BC"); //With out Padding
  //Cipher decrypter = Cipher.getInstance("DESede/CBC/PKCS5Padding", "BC"); //With Padding(PKCS5Padding)
  decrypter.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(new byte[8]));
  return decrypter.doFinal(dataInByte);
 }
    
    
    
    public static String decryptData(String encryptedData,String keySerialNumber) throws Exception {
     DukptAdapter adapter=new DukptAdapter();
     adapter.setUp();
  SecureDESKey bdk = (SecureDESKey) adapter.getBDK("dukpt-bdk");
  KeySerialNumber ksn=adapter.getKSN(keySerialNumber);
  byte[] derivedKey = adapter.getDerivedKey(ksn, bdk);
  byte[] decryptedData=adapter.decrypt(ISOUtil.hex2byte(encryptedData), derivedKey);
  return new String(decryptedData);
 }
    
    private  byte[] encrypt(String text, byte[] derivedKey)throws Exception {
  Security.addProvider(new BouncyCastleProvider());
  SecretKey keySpec = new SecretKeySpec(derivedKey, "DESede");
  Cipher decrypter = Cipher.getInstance("DESede/CBC/Nopadding", "BC"); //With out Padding
  //Cipher decrypter = Cipher.getInstance("DESede/CBC/PKCS5Padding", "BC"); //With Padding(PKCS5Padding)
  decrypter.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(new byte[8]));
  return decrypter.doFinal(text.getBytes());
 }
    
    
    public static String encryptData(String text,String keySerialNumber) throws Exception {
     DukptAdapter adapter=new DukptAdapter();
     adapter.setUp();
  SecureDESKey bdk = (SecureDESKey) adapter.getBDK("dukpt-bdk");
  KeySerialNumber ksn=adapter.getKSN(keySerialNumber);
  byte[] derivedKey = adapter.getDerivedKey(ksn, bdk);
  byte[] encryptedData=adapter.encrypt(text, derivedKey);
  return ISOUtil.hexString(encryptedData);
 }
    
    public static String decryptUnEncryptedData(String text) throws Exception {
  return new String(ISOUtil.hex2byte(text));
 }
    
    public void setUp() throws Exception {
        initSM ();
        initKS ();
    }
    
   public static void showKeyDetails(String keySerialNumber) throws Exception {
  System.out.println("::::::::::::::::::::::::::::::::::Key Details::::::::::::::::::::::::::::::::::::::::::");
  DukptAdapter adapter=new DukptAdapter();
  SimpleConfiguration bdkConfig = new SimpleConfiguration("/tmp/dukpt-bdk");
  SimpleConfiguration lmkConfig = new SimpleConfiguration("/tmp/dukpt-lmk");
  SecureKeyStore ks = new SimpleKeyFile ("/tmp/dukpt-bdk");
  SSM sm = new SSM("/tmp/dukpt-lmk","com.sun.crypto.provider.SunJCE");
  SecureDESKey bdk = (SecureDESKey) ks.getKey ("dukpt-bdk");
  KeySerialNumber ksn=adapter.getKSN(keySerialNumber);
  System.out.println("DUKPT Key Type  :"+bdkConfig.get("dukpt-bdk.type"));
  System.out.println("BDK Key         :"+bdkConfig.get("dukpt-bdk.key"));
  System.out.println("BDK check Value :"+bdkConfig.get("dukpt-bdk.checkvalue"));
  System.out.println("BDK Key Length  :"+bdkConfig.get("dukpt-bdk.length"));
  System.out.println("BDK Class       :"+bdkConfig.get("dukpt-bdk.class"));
  System.out.println("LMK Key         :"+lmkConfig.get("LMK0x09"));
  System.out.println("KSN             :"+keySerialNumber);
  System.out.println("Initial Key     :"+ISOUtil.hexString(sm.calculateInitialKey(ksn, bdk, true)));
  System.out.println("Derived Key     :"+ISOUtil.hexString(sm.calculateDerivedKey(ksn, bdk, true)));
  System.out.println(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::");
 }
}



IdtechAdapter.java
package com.java2depth.dukpt;

/**
 * 
 Header//Compulsory Fixed Length(20 hexString,10 bytes length)
 UnEncryptedTrack1Data//Compulsory Variable length
 UnEncryptedTrack2Data//Compulsory Variable length
 EncryptedTrack1Data//Compulsory Variable length
 EncryptedTrack2Data//Compulsory Variable length
 UnUsedEncryptedData//Optional Variable length
 DeviceSN//Compulsory Fixed Length(20 hexString,10 bytes)
 KSN//Compulsory Fixed Length (20 hexString,10 bytes)
 Footer//Compulsory Fixed Length (6 hexString,3 bytes)
 *
 */

public class IdtechAdapter {

 private static int getUnEncryptedTrack1Length(String encryptedData){
  String header=encryptedData.substring(0, 20);
  String track1LengthInhex=header.substring(10, 12);
  int track1Len=getDecimalFromHex(track1LengthInhex);
  return track1Len*2;
 }
 
 private static int getUnEncryptedTrack2Length(String encryptedData){
  String header=encryptedData.substring(0, 20);
  String track2LengthInhex=header.substring(12, 14);
  int track2Len=getDecimalFromHex(track2LengthInhex);
  return track2Len*2;
 }
 
 private static int getDecimalFromHex(String hex){
  return Integer.parseInt(hex,16);
 }
 
 private static int getEncryptedTrack1Length(String encryptedData){
  int encryptTrack1Len=0;
  String header=encryptedData.substring(0, 20);
  String track1LengthInhex=header.substring(10, 12);
  int track1Len=getDecimalFromHex(track1LengthInhex);
  int track1Flag=track1Len%8;
  if(track1Flag!=0){
    encryptTrack1Len=track1Len+(8-track1Flag);
    encryptTrack1Len=encryptTrack1Len*2;
   }else{
    encryptTrack1Len=track1Len*2;
   }
  return encryptTrack1Len;
 }

 private static int getEncryptedTrack2Length(String encryptedData){
  int encryptTrack2Len=0;
  String header=encryptedData.substring(0, 20);
  String track2LengthInhex=header.substring(12, 14);
  int track2Len=getDecimalFromHex(track2LengthInhex);
  int track2Flag=track2Len%8;
  if(track2Flag!=0){
    encryptTrack2Len=track2Len+(8-track2Flag);
    encryptTrack2Len=encryptTrack2Len*2;
   }else{
    encryptTrack2Len=track2Len*2;
   }
  return encryptTrack2Len;
 }
 
 private static String getHeader(String encryptedData){
  return encryptedData.substring(0, 20);
 }
 
 
 private static String getUnEncryptedTrack1Data(String encryptedData){
  int unEncryptTrack1Length=getUnEncryptedTrack1Length(encryptedData);
  return encryptedData.substring(20, 20+unEncryptTrack1Length);
 }
 
 public static String getUnEncryptedTrack2Data(String encryptedData){
  int unEncryptTrack1Length=getUnEncryptedTrack1Length(encryptedData);
  int unEncryptTrack2Length=getUnEncryptedTrack2Length(encryptedData);
  return encryptedData.substring(20+unEncryptTrack1Length, 20+unEncryptTrack1Length+unEncryptTrack2Length);
 }
 public static String getEncryptedTrack1Data(String encryptedData){
  int unEncryptTrack1Length=getUnEncryptedTrack1Length(encryptedData);
  int unEncryptTrack2Length=getUnEncryptedTrack2Length(encryptedData);
  int encryptTrack1Length=getEncryptedTrack1Length(encryptedData);
  return encryptedData.substring(20+unEncryptTrack1Length+unEncryptTrack2Length, 20+unEncryptTrack1Length+unEncryptTrack2Length+encryptTrack1Length);
 }
 public static String getEncryptedTrack2Data(String encryptedData){
  int unEncryptTrack1Length=getUnEncryptedTrack1Length(encryptedData);
  int unEncryptTrack2Length=getUnEncryptedTrack2Length(encryptedData);
  int encryptTrack1Length=getEncryptedTrack1Length(encryptedData);
  int encryptTrack2Length=getEncryptedTrack2Length(encryptedData);
  return encryptedData.substring(20+unEncryptTrack1Length+unEncryptTrack2Length+encryptTrack1Length,20+unEncryptTrack1Length+unEncryptTrack2Length+encryptTrack1Length+encryptTrack2Length);
 }
 
 private static String getUnUsedEncryptedData(String encryptedData){
  int unEncryptTrack1Length=getUnEncryptedTrack1Length(encryptedData);
  int unEncryptTrack2Length=getUnEncryptedTrack2Length(encryptedData);
  int encryptTrack1Length=getEncryptedTrack1Length(encryptedData);
  int encryptTrack2Length=getEncryptedTrack2Length(encryptedData);
  return encryptedData.substring(20+unEncryptTrack1Length+unEncryptTrack2Length+encryptTrack1Length+encryptTrack2Length, encryptedData.length()-46);
 }
 
 private static String getDeviceID(String encryptedData){
  return encryptedData.substring(encryptedData.length()-46, encryptedData.length()-26);
 }
 
 public static String getKSN(String encryptedData){
  return encryptedData.substring(encryptedData.length()-26, encryptedData.length()-6);
 }
 
 private static String getFooter(String encryptedData){
  return encryptedData.substring(encryptedData.length()-6, encryptedData.length());
 }
 
 public static String decryptData(String encryptedData) throws Exception{
  String track1=DukptAdapter.decryptData(getEncryptedTrack1Data(encryptedData),getKSN(encryptedData));
  String track2=DukptAdapter.decryptData(getEncryptedTrack2Data(encryptedData),getKSN(encryptedData));
  System.out.println("::::::::::::::::::::::::::::::::::Decrypt The Encrypted Data::::::::::::::::::::::::::::::::::::::::::");
  System.out.println("Track 1 Data   :"+track1.trim());
  System.out.println("Track 2 Data   :"+track2.trim());
  System.out.println("Decrypted Data :"+track1.trim()+" "+track2.trim());
  System.out.println(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::");
  return track1.trim()+" "+track2.trim();
 }
 
 public static String decryptUnEncryptedData(String text) throws Exception{
  System.out.println("::::::::::::::::::::::::::::::::::Decrypt The UnEncrypted Data::::::::::::::::::::::::::::::::::::::::::");
  String track1=DukptAdapter.decryptUnEncryptedData(getUnEncryptedTrack1Data(text));
  String track2=DukptAdapter.decryptUnEncryptedData(getUnEncryptedTrack2Data(text));
  System.out.println("Track 1 Data   :"+track1);
  System.out.println("Track 2 Data   :"+track2);
  System.out.println("Decrypted Data :"+track1.trim()+" "+track2.trim());
  System.out.println(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::");
  return track1.trim()+" "+track2.trim();
 }
 
 public static String enryptData(String text,String ksn) throws Exception{
  if(text.length()%8!=0)
   throw new Exception("Text SIze is not Multiple Of 8, Size is "+text.length());
  String encryptedData=DukptAdapter.encryptData(text,ksn);
  return encryptedData;
 }
 
 public static void showRequestDetails(String encryptedData) throws Exception {
  System.out.println("::::::::::::::::::::::::::::::::::Request Details::::::::::::::::::::::::::::::::::::::::::");
  System.out.println("Original Request      :"+encryptedData);
  System.out.println("Header                :"+getHeader(encryptedData));//Compulsory Fixed Length(20 hexString,10 bytes length)
  System.out.println("UnEncryptedTrack1Data :"+getUnEncryptedTrack1Data(encryptedData));//Compulsory Variable length
  System.out.println("UnEncryptedTrack2Data :"+getUnEncryptedTrack2Data(encryptedData));//Compulsory Variable length
  System.out.println("EncryptedTrack1Data   :"+getEncryptedTrack1Data(encryptedData));//Compulsory Variable length
  System.out.println("EncryptedTrack2Data   :"+getEncryptedTrack2Data(encryptedData));//Compulsory Variable length
  System.out.println("UnUsedEncryptedData   :"+getUnUsedEncryptedData(encryptedData));//Optional Variable length
  System.out.println("DeviceSN              :"+getDeviceID(encryptedData));//Compulsory Fixed Length(20 hexString,10 bytes)
  System.out.println("KSN                   :"+getKSN(encryptedData));//Compulsory Fixed Length (20 hexString,10 bytes)
  System.out.println("Footer                :"+getFooter(encryptedData));//Compulsory Fixed Length (6 hexString,3 bytes)
  System.out.println(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::");
  DukptAdapter.showKeyDetails(getKSN(encryptedData));
 }
}


DukptDecryption.java
package com.java2depth.dukpt;

import org.jpos.security.jceadapter.DukptAdapter;
import org.jpos.security.jceadapter.IdtechAdapter;

public class DukptDecryption {
 
 public static void main(String[] args) throws Exception { 
    String encryptedData="02D500801F3723008383252A353135302A2A2A2A2A2A2A2A373836315E504159504153532F4D4153544552434152445E2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A3F2A3B353135302A2A2A2A2A2A2A2A373836313D2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A3F2AA096A6F5D1DCBE45B5F77EB2559FEE0411013232E3F42044C0397E3E9E6D9B3A11FB8ADE0712AFD097C23AA86DFDC9DBA0E73A6FD698FD2F80800C0E1E9ED1BEED5EEA9840DA53F41254FDB79E89B76B127C25FE44AE7524BAEB5BDAACF777FA31323334353637383930FFFF9876543210E0004ABBF903";
    IdtechAdapter.showRequestDetails(encryptedData);
    IdtechAdapter.decryptUnEncryptedData(encryptedData);
    IdtechAdapter.decryptData(encryptedData);    
    String track1Data=DukptAdapter.decryptData(IdtechAdapter.getEncryptedTrack1Data(encryptedData),IdtechAdapter.getKSN(encryptedData));
    String track2Data=DukptAdapter.decryptData(IdtechAdapter.getEncryptedTrack2Data(encryptedData),IdtechAdapter.getKSN(encryptedData));
    String ksn=IdtechAdapter.getKSN(encryptedData);
    
    System.out.println("ksn: "+ksn);
    
    System.out.println("track1Data: "+track1Data);
    System.out.println("track1Data Length: "+track1Data.length());
    System.out.println("track1Data(Trim): "+track1Data.trim().length());
    System.out.println("Encrypted Track1Data: "+DukptAdapter.encryptData(track1Data,ksn));
    
    System.out.println("track2Data: "+track2Data);
    System.out.println("track2Data Length: "+track2Data.length());
    System.out.println("track2Data(Trim): "+track2Data.trim().length());
    System.out.println("Encrypted Track2Data: "+DukptAdapter.encryptData(track2Data,ksn));
    
    
  /*  
    String encryptedData = DukptAdapter.encryptData("123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678","62994948360000600237");
    System.out.println("Encrypted Track2Data: "+encryptedData);
    System.out.println("Encrypted Track2Data: "+DukptAdapter.decryptData(encryptedData,"62994948360000600237"));*/  
 }
}


Input : 
02D500801F3723008383252A353135302A2A2A2A2A2A2A2A373836315E504159504153532F4D4153544552434152445E2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A3F2A3B353135302A2A2A2A2A2A2A2A373836313D2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A3F2AA096A6F5D1DCBE45B5F77EB2559FEE0411013232E3F42044C0397E3E9E6D9B3A11FB8ADE0712AFD097C23AA86DFDC9DBA0E73A6FD698FD2F80800C0E1E9ED1BEED5EEA9840DA53F41254FDB79E89B76B127C25FE44AE7524BAEB5BDAACF777FA31323334353637383930FFFF9876543210E0004ABBF903

Output :
::::::::::::::::::::::::::::::::::Request Details::::::::::::::::::::::::::::::::::::::::::
Original Request      :02D500801F3723008383252A353135302A2A2A2A2A2A2A2A373836315E504159504153532F4D4153544552434152445E2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A3F2A3B353135302A2A2A2A2A2A2A2A373836313D2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A3F2AA096A6F5D1DCBE45B5F77EB2559FEE0411013232E3F42044C0397E3E9E6D9B3A11FB8ADE0712AFD097C23AA86DFDC9DBA0E73A6FD698FD2F80800C0E1E9ED1BEED5EEA9840DA53F41254FDB79E89B76B127C25FE44AE7524BAEB5BDAACF777FA31323334353637383930FFFF9876543210E0004ABBF903
Header                :02D500801F3723008383
UnEncryptedTrack1Data :252A353135302A2A2A2A2A2A2A2A373836315E504159504153532F4D4153544552434152445E2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A3F2A
UnEncryptedTrack2Data :3B353135302A2A2A2A2A2A2A2A373836313D2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A3F2A
EncryptedTrack1Data   :A096A6F5D1DCBE45B5F77EB2559FEE0411013232E3F42044C0397E3E9E6D9B3A11FB8ADE0712AFD097C23AA86DFDC9DBA0E73A6FD698FD2F
EncryptedTrack2Data   :80800C0E1E9ED1BEED5EEA9840DA53F41254FDB79E89B76B127C25FE44AE7524BAEB5BDAACF777FA
UnUsedEncryptedData   :
DeviceSN              :31323334353637383930
KSN                      :FFFF9876543210E0004A
Footer                   :BBF903
::::::::::::::::::::::::::::::::::::Key Details::::::::::::::::::::::::::::::::::::::::::
DUKPT Key Type  :BDK
BDK Key                :26FB71EA0C9CBBA1D51CA00CFFA36374
BDK check Value   :08D7B4
BDK Key Length   :128
BDK Class              :org.jpos.security.SecureDESKey
LMK Key               :5152DA52D5BF1A26D9F826E307973BB05152DA52D5BF1A26
KSN                        :FFFF9876543210E0004A
Initial Key              :6AC292FAA1315B4D858AB3A3D7D5933A
Derived Key           :6220B23D0B06787F73C17FB6FD9590E0
::::::::::::::::::::::::::Decrypt The UnEncrypted Data::::::::::::::::::::::::::::::::::::::::::
Track 1 Data   :%*5150********7861^PAYPASS/MASTERCARD^***************?*
Track 2 Data   :;5150********7861=***************?*
Decrypted Data :%*5150********7861^PAYPASS/MASTERCARD^***************?* ;5150********7861=***************?*
::::::::::::::::::::::::::Decrypt The Encrypted Data::::::::::::::::::::::::::::::::::::::::::
Track 1 Data   :%B5150710200107861^PAYPASS/MASTERCARD^090910140000202?>
Track 2 Data   :;5150710200107861=090910140000202?1
Decrypted Data :%B5150710200107861^PAYPASS/MASTERCARD^090910140000202?> ;5150710200107861=090910140000202?1



Inform:

3 comments: