Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Following the Neptune Lite version update(Nepture NeptuneLiteApi_V4.02.00_20230921), we can now perform iso4 pin mode.

The obtained KSN will be in the format below:

...

Depending on the length of your AES key, you may choose between AES 128, AES 192, AES 256.

An example code will be provided below on the creation of the online pin and then the message creation.

Code Block
languagejava
  public int do_online_pin(byte[] bytes) {
        int ret = 0;
        Log.d("do_online_pin","Starting online pin");
        EnterPinFragment.openDialog();
        try {
            String expectPinLen = "4,5,6,7,8,9,10,11,12";
            //ped.setKeyboardLayoutLandscape(false);
            ped.setInputPinListener(EnterPinFragment.pedInputListener);
            EnterPinFragment.setExpectPinLen(expectPinLen);
            ped.setKeyboardRandom(false);
            //ped.inputPin(expectPinLen, 300000, (byte)0x00);
            TlvTree txContext = TlvTree.FromRaw(bytes);
            String PAN = txContext.GetElementAscii(0xC7);
            PAN = "0000" + PAN.substring(PAN.length() - 13, PAN.length() - 1);
            byte[] accountNb = new byte[16];
            for (int i = 0; i < 16; i++) {
                accountNb[i] = Byte.parseByte(PAN.substring(i, i+1));
            }
            incrementKSNIfNecessary();
            pindukptResult = ped.getAesDUKPTPin((byte)0x01,expectPinLen, accountNb, EAlgorithmType._AES128_, (byte) 0x24,300000);

            String ksn = bytesToHex(pindukptResult.getKsn());
            Log.d("pin", "ksn is:" + ksn);

            String result = bytesToHex(pindukptResult.getResult());
            Log.d("pin", "result is:" + result);

        } catch (PedDevException e) {
            e.printStackTrace();
            ret = 1;
        }
        EnterPinFragment.closeDialog();
        return ret;
    }

It is important to note that ISO4 == 0x24.

You can refer to Pax documentation if it is unclear.

...

The obtained KSN will be 12 bytes long.

Code Block
languagejava
    public byte[] getOnlinePin(byte [] data) {

        Log.d("getOnlinePin", "Getting pin block");

        DUKPTResult result = pindukptResult;

        byte [] encryptedPinBlock = result.getResult();
        byte [] ksn = result.getKsn();

        Log.d("getOnlinePin", "KSN is : " + hex(ksn) + " and encrypted pinblock is " + hex(encryptedPinBlock));
        StringBuilder message = new StringBuilder();
        message.append("<CrdhldrOnLinePIN>" +
                "<NcrptdPINBlck>" +
                "<CnttTp>EVLP</CnttTp>" +
                "<EnvlpdData>" +
                "<Vrsn>1</Vrsn>" +
                "<Rcpt>" +
                "<KEK>" +
                "<Vrsn>1</Vrsn>" +
                "<KEKId>" +
                "<KeyId>nexoAESD128TestKey</KeyId>" +
                "<KeyVrsn>20190522</KeyVrsn>" +
                "<SeqNb>1</SeqNb>" +
                "<DerivtnId>" + Base64.encodeToString(Arrays.copyOfRange(ksn, 0, 5), Base64.NO_WRAP) + "</DerivtnId>" +
                "</KEKId>" +
                "<KeyNcrptnAlgo>" +
                "<Algo>DA12</Algo>" +
                "</KeyNcrptnAlgo>" +
                "<NcrptdKey>" + Base64.encodeToString(Arrays.copyOfRange(ksn, 5, 12), Base64.NO_WRAP) + "</NcrptdKey>" +
                "</KEK>" +
                "</Rcpt>" +
                "<NcrptdCntt>" +
                "<CnttTp>DATA</CnttTp>" +
                "<CnttNcrptnAlgo>" +
                "<Algo>EA2C</Algo>" +
                "</CnttNcrptnAlgo>" +
                "<NcrptdData>" + Base64.encodeToString(encryptedPinBlock, Base64.NO_WRAP) + "</NcrptdData>" +
                "</NcrptdCntt>" +
                "</EnvlpdData>" +
                "</NcrptdPINBlck>" +
                "<PINFrmt>ISO4</PINFrmt>" +
                "</CrdhldrOnLinePIN>");

        TlvTree cardholderpin = TlvTree.Empty();
        cardholderpin.AddEnum(0xDF9F34, 0);
        cardholderpin.AddAscii(0xDF9F14, message.toString());

        Log.d("getOnlinePin", cardholderpin.Stringify());

        return cardholderpin.AsBytes();
    }