node-tlv
node base tlv parser
Example for parse FCI
const TLV = require('node-tlv');
const assert = require('assert');
// 6F20840E315041592E5359532E4444463031A50E8801015F2D046B6F656E9F110101
const resp = '6F20840E315041592E5359532E4444463031A50E8801015F2D046B6F656E9F110101';
const tlv = TLV.parse(resp);
assert(tlv.getTag() === '6F');
assert(tlv.getLength() === 0x20);
// find dedicated file name
const df_name = tlv.find('84')
// find FCI Proprietary Template
const fci_prop_template = tlv.find('A5')
Example for parse GPO response
const TLV = require('node-tlv');
const assert = require('assert');
// parse TLV
const resp = '770E8202580094080801010010010301';
const tlv = TLV.parse(resp);
// response message template
assert(tlv.getTag() === '77');
assert(tlv.getLength() === 14);
assert(tlv.getValue() == '8202580094080801010010010301');
// get TLV array
const child = tlv.getChild();
assert(child.length === 2);
const first = child[0];
assert(first.getTag() === '82');
// find AIP
const aip = tlv.find(0x82);
assert(aip.getTag() === '82');
assert(aip.getLength() === 2);
assert(aip.getValue() === '5800');
// you can also use a string tag value
const afl = tlv.find('94');
assert(afl.getTag() === '94');
assert(afl.getLength() === 0x08);
assert(afl.getValue() === '0801010010010301');
Example for parse PSE Record
const TLV = require('node-tlv');
const assert = require('assert');
const resp = '702961134F08A0000000250104025004414D455887010161124F07A00000002910105004414D4558870102'
const tlv = TLV.parse(resp);
// find multiple tags
const directory_enties = tlv.findAll('61')
assert(directory_enties.length() === 2);
const directory_entry_1 = directory_enties[0];
var adf_name = directory_entry_1.find('4f');
assert(adf_name.getTag() === '4F');
assert(adf_name.getLength() > 5);
assert(adf_name.getLength() < 16);
var application_label = directory_entry_1.find('50');
assert(application_label.getTag() === '50');
assert(application_label.getLength() > 1);
assert(application_label.getLength() < 16);
Exmaple for build PPSE FCI
// EMV Contactless Book B Entry Point Specification
// Table 3-2: SELECT Response Message Data Field (FCI) of the PPSE
//'6F' FCI Template M
// '84' DF Name (‘2PAY.SYS.DDF01’) O
// 'A5' FCI Proprietary Template M
// 'BF0C' FCI Issuer Discretionary Data M
// '61' Directory Entry M
// '4F' ADF Name M
// '50' Application Label O
// example for my credit card real data
// CAPDU: 00A404000E325041592E5359532E4444463031
// RAPDU: 6F2C840E325041592E5359532E4444463031A51ABF0C1761154F07A0000000031010500A56495341435245444954
// 6F 2C(44) [FCI Template]
// 84 0E(14) [DF Name]: 325041592E5359532E4444463031
// A5 1A(26) [FCI Proprietary Template]
// BF0C 17(23) [FCI Issuer Discretionary Data]
// 61 15(21) [Directory Entry]
// 4F 07( 7) [ADF Name]: A0000000031010
// 50 0A(10) [Application Label]: VISACREDIT
const TLV = require('node-tlv');
const assert = require('assert');
// step 1 build leaf
const df_name = new TLV('84', '325041592E5359532E4444463031'); // DF name for PPSE
const adf_name = new TLV('4F', 'A0000000031010'); // aid for visa
const app_label = new TLV('50', '56495341435245444954'); // VISACREDIT
// step 2 build directory entry '61'
const dir_encty = new TLV('61', adf_name.getTLV()+app_label.getTLV());
// step 3 build FCI Issuer Discretionary data ' BF0C'
const issuer_discretionary_data = new TLV('BF0C', dir_encty.getTLV());
// step 4 build FCI Proprietary Template 'A5'
const fci_proprietary_template = new TLV('A5', issuer_discretionary_data.getTLV());
// step 5 build FCI template '6F'
const fci_template = new TLV('6F', df_name.getTLV() + fci_proprietary_template.getTLV());
assert(fci_template.getTLV() === '6F2C840E325041592E5359532E4444463031A51ABF0C1761154F07A0000000031010500A56495341435245444954');
Exmaple for build PSE record
// EMV 4.3 Book 1
// Table 46: Payment System Directory Record Format
// Tag '70' | Data Length (L) | Tag '61' | Length | Directory entry 1 (ADF)
// EMV 4.3 Book 1
// Table 47: ADF Directory Entry Format
// '4F' 5–16 ADF Name M
// '50' 1–16 Application Label M
// '9F12' 1–16 Application Preferred Name O
// '87' 1 Application Priority Indicator O
// '73' var. Directory Discretionary Template O
// CAPDU: 00B2010C00
// RAPDU: 702861264F07A0000000041010870101500A4D4153544552434152449F120B43495449204D4153544552
// 70 28(40) [READ RECORD Response Message Template]
// 61 26(38) [Directory Entry]
// 4F 07( 7) [ADF Name]: A0000000041010
// 87 01( 1) [Application Priority Indicator]: 01
// 50 0A(10) [Application Label]: MASTERCARD
// 9F12 0B(11) [Application Preferred Name]: CITI MASTER
const TLV = require('node-tlv');
const assert = require('assert');
// step 1 build leaf
const adf_name = new TLV('4F', 'A0000000041010'); // aid for mastercard
const app_priority = new TLV('87', '01');
const app_label = new TLV('50', '4D415354455243415244'); // MASTERCARD
const app_pref_name = new TLV('9F12', '43495449204D4153544552'); // CITI MASTER
// step 2 build directory entry '61'
const dir_entry = new TLV('61', adf_name + app_priority + app_label + app_pref_name);
// step 3 build read record response message template
const record_template = new TLV('70', dir_entry.getTLV());
assert(record_template.toString() === '702861264F07A0000000041010870101500A4D4153544552434152449F120B43495449204D4153544552');
Installation
You can install the latest tag via npm:
npm install node-tlv
##Use node-tlv-parser