Doing PIN Translation with DUKPT

On PIN-enabled Debit/EBT transactions sent in from an acquirer’s point-of-sale location, your payment switch application must perform a PIN translation, typically transforming an incoming DUKPT PIN block from the POS device-initiated request into a outgoing Triple DES-encrypted PIN block that makes use of an established Zone PIN Key (“ZPK”) which would have been previously established via a dynamic key exchange with your Debit/EBT gateway provider.

[The remainder of this example assumes you’re using a Thales (formerly Racal) Hardware Security Module (“HSM”)….] Using strict Thales parlance, this variant of a PIN translation request is a request to “translate a PIN from *BDK encryption to interchange key encryption.”  This topic is covered in Section 27.2 (page 2-185) of the Thales reference document entitled “Host Security Module RG7000 Programmer’s Manual” (Thales reference number 1270A514 Issue 5). The CI/CJ exchange should be handled as follows: — CI — Message header – You can use as you see fit. Value is echoed back in CJ.  Note that the length is constant and must be configured in HSM by administrator. Command code – CI BDK – The Base Derivation Key “in play” for this transaction.  In my installations we’ve set this up as follows…

  • Selected the “1A + 32H” option, where the ‘1A’ value should be set to ‘U’
  • Configured such that the first six positions of the KSN represent the “key name” of the BDK injected into the PIN Pad at the transaction origination point (an acquirer can use a number of BDKs in their terminal population).

ZPK – Your current ZPK Cryptogram (obtained dynamically via a key exchange with your Debit/EBT  gateway partner) and stored under your Local Master Key (“LMK”).  In my installations, we’ve used the “1A + 32H” option, where the ‘1A’ value should be set to ‘U’. KSN Descriptor – This value is a bit esoteric and refers directly to the make-up of the KSN which follows.  So to understand the descriptor, it’s first necessary to talk a bit about the KSN (the next field in the CI command layout).  Here’s a typical KSN implementation where the acquirer has chosen a 16-position scheme:

  • Positions 1 – 6: The name of the BDK injected into this device
  • Positions 7 – 11:  The device ID
  • Positions 12 – 16: The transaction counter

[Note that the KSN implementation has to be in synch between the PIN pad and your host-side implementations in order for this to work.] The ‘rules’ for a KSN construction are as follows (reading from left to right in the KSN): a. The ‘base derivation key identifier,’ which is mandatory and five to nine (Hex) positions in length. b. A ‘sub-key identifier,’ which Thales says is ‘optional’ but in practice is ‘reserved for future use’ (and therefore always set to zero). c. A ‘device identifier’ (mandatory), which is two to five Hex digits in length. d. A ‘transaction counter’ (mandatory) which essentially is the part “left over”. So, in the example here, the client with a 6, 0, 5, 5 implementation. With this information in hand, the KSN Descriptor (a three-position value) is better described as XYZ, where: X = base derivation key identifier length Y = sub-key identifier key length (will be zero) Z = device identifier length So, in this context, the ‘605’ submitted in my example is better visualized. ‘605’ says that the 16-digit KSN consists of a 6-position BDK ID, a 0-position sub-key, a 5-position device ID, **AND** (what’s remaining basically) a 5-position transaction counter. [NOTE: Remember that this post applies *specifically* to the Thales/RACAL implementation of PIN translation] Now, with this informatation in hand, we can introduce the next field, the KSN itself… KSN – Using the layout from the descriptor, a typical KSN at this acquirer might be 123456000A8001D4 where: ‘123456’ is the BDK indentifier; ‘000A8’ is the Device ID; and ‘001D4’ is the transaction counter. The BDK name embedded in a particular KSN string must find a match within your BDK cryptogram list (which you need to keep loaded into your payment switch’s encryption database).  If a match is not found in the encryption database, then set your Internal Result Code to “Invalid BDK” and end the transaction.  If found, the value you retrieve goes into the BDK field (as described above). Source encrypted block – The PIN block plucked from the POS device request (this is a 16H value; no ‘1A’ indicator is required). Destination PIN block – In my installations, we typically use ANSI format, so we set this to ‘01’ to signify ANSI format code Account Number – Right-most 12 positions of the PAN excluding the check digit Typically, that is the END of the required CI request message (remainder of the fields in the Thales spec are not mandatory). — CJ — Message header – Echoed back from CI usage. Response code – CJ Error Code – Only ‘00’ should be accepted as an exchange that “worked.” PIN length – Although this field is not used to build the 0200 message formatted for your Debit/EBT gateway, a value like ‘04’ or ‘05’ here are a pretty good indication that the translation occurred successfully. Encrypted PIN – The PIN block that will be used to build the 0200 message formatted for your Debit/EBT gateway (this is a 16H value; no ‘1A’ indicator is required). Destination PIN block – Echoed back from the device as ’01’ format code Typically, that is the END of the response message (remainder of list in the vendor spec would only be present if they were provided in the CI command request)