Ejemplo n.º 1
0
def parse_transaction_log_records(log_format_str, log_record_strings):
    '''
    return (csv_header_line, [csv_record_line])
    '''

    log_format_byte_list = bit_tools.hex_string_to_byte_list(log_format_str)
    log_format = tlv_utils.parse_concatted_dol_list_to_ordered_list_of_tag_and_length(
        log_format_byte_list)

    records = []
    for record_string in log_record_strings:
        records.append(bit_tools.hex_string_to_byte_list(record_string))

    parsed_records = []
    for orig_rec in records:

        rec = list(orig_rec)

        parsed = []
        for (tag_name, tag_length) in log_format:
            value = []
            for i in range(tag_length):
                value.append(rec.pop(0))
            parsed.append(value)

        parsed_records.append(parsed)

    #fname = 'c:/dev/logs/parsed_txn_log.log'
    #f = open(fname, 'w')

    csv_header = ','.join([
        tag_meanings.emv_tags[tag_name]
        for (tag_name, tag_length) in log_format
    ])
    #f.write(headers + '\n')

    csv_lines = []

    for parsed_rec in parsed_records:
        csv_string = ''
        for rec_element in parsed_rec:
            csv_string = (csv_string +
                          bit_tools.byte_list_to_hex_string(rec_element) + ',')
        csv_lines.append(csv_string)

    #for line in csv_lines:
    #    f.write(line + '\n')

    #f.close()

    return (csv_header, csv_lines)
Ejemplo n.º 2
0
def parse_transaction_log_records(log_format_str, log_record_strings):
    '''
    return (csv_header_line, [csv_record_line])
    '''    
    
    log_format_byte_list = bit_tools.hex_string_to_byte_list(log_format_str)
    log_format = tlv_utils.parse_concatted_dol_list_to_ordered_list_of_tag_and_length(log_format_byte_list)
    
    records = []
    for record_string in log_record_strings:
        records.append(bit_tools.hex_string_to_byte_list(record_string))
    
    parsed_records = []
    for orig_rec in records:
        
        rec = list(orig_rec)
        
        parsed = []        
        for (tag_name, tag_length) in log_format:
            value = []
            for i in range(tag_length):
                value.append(rec.pop(0))
            parsed.append(value)
        
        parsed_records.append(parsed)

    #fname = 'c:/dev/logs/parsed_txn_log.log'
    #f = open(fname, 'w')
    
    csv_header = ','.join([tag_meanings.emv_tags[tag_name] for (tag_name, tag_length) in log_format])
    #f.write(headers + '\n')
    
    csv_lines = []    
    
    for parsed_rec in parsed_records:
        csv_string = ''
        for rec_element in parsed_rec:
            csv_string = (csv_string + bit_tools.byte_list_to_hex_string(rec_element) + ',') 
        csv_lines.append(csv_string)

    #for line in csv_lines:
    #    f.write(line + '\n')

    #f.close()
    
    return (csv_header, csv_lines)
Ejemplo n.º 3
0
def get_afl_aip_via_processing_options(connection, pdol=None):
    '''
    return afl or None
    
    EMV 4.2 Book 3 - 6.5.8, 6.5.8.4
    - App Interchange Profile
    - Appp File Locator
    
    EMV 4.2 Book 3 5.4 = Data Object List - DOL
    
    ----------------------------------------------------------------------------------------------
    
    [ EMV 4.2 Book 3 - Application Specification - 10.1 Initiate Application Processing ]
    
    The PDOL is a list of tags and lengths of terminal-resident data elements needed by the ICC 
    in processing the GET PROCESSING OPTIONS command. Only data elements having the terminal as 
    the source of the data may be referenced in the PDOL. If the PDOL does not exist, the GET 
    PROCESSING OPTIONS command uses a command data field of '8300', indicating that the length 
    of the value field in the command data is zero.

    There may be some exceptions in the timing for this. For example, these bits could be set to 
    0 at the completion of the previous transaction or prior to application selection of this 
    transaction. The intent here is that the processing steps as described in the Application 
    Specification presume the bits have been initialised to 0.

    If the PDOL exists, the terminal extracts the PDOL from the FCI of the ADF and uses it to 
    create a concatenated list of data elements without tags or lengths. The rules specified 
    in section 5.4 apply to processing of the PDOL. If an amount field (either Amount, Authorised 
    or Amount, Other) is referenced in the PDOL and the terminal is unable to provide the amount 
    at this point in transaction processing, the amount field in the data element list shall be 
    filled with hexadecimal zeroes. The terminal issues the GET PROCESSING OPTIONS command using 
    either the command data field of '8300' (if there was no PDOL in the ICC) or a data object 
    constructed with a tag of '83' and the appropriate length according to BER-TLV encoding rules 
    and a value field that is the concatenated list of data elements resulting from processing the 
    PDOL.
    
    The card returns either:
    - The Application Interchange Profile the Application File Locator (identifying the files and 
    records containing the data to be used for the transaction), and status SW1 SW2 = '9000', or
    - Status SW1 SW2 = '6985' (Conditions of use not satisfied), indicating that the transaction 
    cannot be performed with this application.

    The format of the response message is given in section 6.5.8. If the status words '6985' are 
    returned, the terminal shall eliminate the current application from consideration and return to 
    the Application Selection function to select another application.
    '''    
    
    # APDU = GET PROCESSING OPTIONS
    data = default_dol = [0x83, 0x00] # tag = 83, length = 0
    
    if (pdol != None):
        data = [0x83]        
        
        concatted = []        
        tags_with_length = tlv_utils.parse_concatted_dol_list_to_ordered_list_of_tag_and_length(pdol)
        for (tag, tag_length) in tags_with_length:            
            
            # TERMINAL COUNTRY CODE
            if (tag == '9F1A'): 
                terminal_country_code_ZAR = [0x07, 0x10]
                concatted.extend(terminal_country_code_ZAR)
                
            # '81':'Amount Authorised (Binary)',
            # '9F02':'Amount Authorised (Numeric)',
            # '9F03':'Amount Other (Numeric)',
            # '9F04':'Amount Other (Binary)',
            
            elif (tag in ['81', '9F02', '9F03', '9F04']):
                for i in range(tag_length):
                    concatted.append(0x00)
            
            else:
                msg = '! Unknown PDOL Tag %s' % tag
                logging.info(msg)
                raise Exception(msg)
                    
        data.append(len(concatted))
        data.extend(concatted)    
    
    ret_data, sw1, sw2 = select_and_requery(connection=connection, 
                                            cla=GET_PROCESSING_OPTIONS.cla, 
                                            ins=GET_PROCESSING_OPTIONS.ins, 
                                            p1=0x00, 
                                            p2=0x00, 
                                            data=data, 
                                            le=0x00)
    
    if DO_LOG:
        logging.info('\n' + 'GET PROCESSING OPTIONS - REQUEST PDOL')
        for x in report_on_reply(sw1, sw2, ret_data):
            logging.info(x) 
    
    # 0x77 0x16 0x82 0x02 0x38 0x00 0x94 0x10 0x08 0x01 0x02 0x00 0x10 0x01 0x02 0x00 0x18 0x01 0x02 0x01 0x20 0x01 0x02 0x00
    # 77 = Format 2 Type Response
    # 77 16 82023800941008010200100102001801020120010200
    # 82 = AIP = Application Interchange Profile
    # 82 02 3800
    # 94 = AFL = Application File Locator
    # 94 10 08010200100102001801020120010200
    #
    # AFL = 08 01 02 00 
    #       10 01 02 00
    #       18 01 02 01
    #       20 01 02 00
    #                      SFI 1st Last OMA-Involved
    # 08 = 8  => 00001000 => 1  01   02           00 
    # 10 = 16 => 00010000 => 2  01   02           00 
    # 18 = 24 => 00011000 => 3  01   02           01
    # 20 = 32 => 00100000 => 4  01   02           00
    
    get_proc_options_format_1_tags = ['80']
    get_proc_options_format_2_tags = ['77', '82', '94']
    
    combined_tags = []
    combined_tags.extend(get_proc_options_format_1_tags)
    combined_tags.extend(get_proc_options_format_2_tags)
    
    '''
    hex_string = bit_tools.byte_list_to_hex_string(ret_data)
    file = open('c:/dev/logs/pdol.txt', 'w')
    file.write(hex_string + '\n')
    file.close()
    '''
    
    tlv_tree = tlv_utils.parse_tlv(ret_data, known_tags=combined_tags)
    
    afl = None
    
    # FORMAT 1 - Visa
    if (get_proc_options_format_1_tags[0] in tlv_tree.distinct_tag_list()):
        node = tlv_tree.get_nodes_for_qtag('80')[0]
        aip_afl = node.value_byte_list
        aip_length = 2
        aip = aip_afl[0:aip_length]
        afl = aip_afl[aip_length:]     
        
        if DO_LOG:
            logging.info('AIP_AFL = ' + '.'.join(['%02X' % b for b in aip_afl]))
            logging.info('AIP     = ' + '.'.join(['%02X' % b for b in aip]))
            logging.info('AFL     = ' + '.'.join(['%02X' % b for b in afl]))
    
    # FORMAT 2 - MasterCard
    else:
        node = tlv_tree.get_nodes_for_qtag('77.94')[0]
        afl = node.value_byte_list
        node = tlv_tree.get_nodes_for_qtag('77.82')[0]
        aip = node.value_byte_list
    
    if DO_LOG:
        logging.info('')
        for line in tlv_tree.report():
            logging.info(line)
        
    return afl, aip
Ejemplo n.º 4
0
def get_afl_aip_via_processing_options(connection, pdol=None):
    '''
    return afl or None
    
    EMV 4.2 Book 3 - 6.5.8, 6.5.8.4
    - App Interchange Profile
    - Appp File Locator
    
    EMV 4.2 Book 3 5.4 = Data Object List - DOL
    
    ----------------------------------------------------------------------------------------------
    
    [ EMV 4.2 Book 3 - Application Specification - 10.1 Initiate Application Processing ]
    
    The PDOL is a list of tags and lengths of terminal-resident data elements needed by the ICC 
    in processing the GET PROCESSING OPTIONS command. Only data elements having the terminal as 
    the source of the data may be referenced in the PDOL. If the PDOL does not exist, the GET 
    PROCESSING OPTIONS command uses a command data field of '8300', indicating that the length 
    of the value field in the command data is zero.

    There may be some exceptions in the timing for this. For example, these bits could be set to 
    0 at the completion of the previous transaction or prior to application selection of this 
    transaction. The intent here is that the processing steps as described in the Application 
    Specification presume the bits have been initialised to 0.

    If the PDOL exists, the terminal extracts the PDOL from the FCI of the ADF and uses it to 
    create a concatenated list of data elements without tags or lengths. The rules specified 
    in section 5.4 apply to processing of the PDOL. If an amount field (either Amount, Authorised 
    or Amount, Other) is referenced in the PDOL and the terminal is unable to provide the amount 
    at this point in transaction processing, the amount field in the data element list shall be 
    filled with hexadecimal zeroes. The terminal issues the GET PROCESSING OPTIONS command using 
    either the command data field of '8300' (if there was no PDOL in the ICC) or a data object 
    constructed with a tag of '83' and the appropriate length according to BER-TLV encoding rules 
    and a value field that is the concatenated list of data elements resulting from processing the 
    PDOL.
    
    The card returns either:
    - The Application Interchange Profile the Application File Locator (identifying the files and 
    records containing the data to be used for the transaction), and status SW1 SW2 = '9000', or
    - Status SW1 SW2 = '6985' (Conditions of use not satisfied), indicating that the transaction 
    cannot be performed with this application.

    The format of the response message is given in section 6.5.8. If the status words '6985' are 
    returned, the terminal shall eliminate the current application from consideration and return to 
    the Application Selection function to select another application.
    '''

    # APDU = GET PROCESSING OPTIONS
    data = default_dol = [0x83, 0x00]  # tag = 83, length = 0

    if (pdol != None):
        data = [0x83]

        concatted = []
        tags_with_length = tlv_utils.parse_concatted_dol_list_to_ordered_list_of_tag_and_length(
            pdol)
        for (tag, tag_length) in tags_with_length:

            # TERMINAL COUNTRY CODE
            if (tag == '9F1A'):
                terminal_country_code_ZAR = [0x07, 0x10]
                concatted.extend(terminal_country_code_ZAR)

            # '81':'Amount Authorised (Binary)',
            # '9F02':'Amount Authorised (Numeric)',
            # '9F03':'Amount Other (Numeric)',
            # '9F04':'Amount Other (Binary)',

            elif (tag in ['81', '9F02', '9F03', '9F04']):
                for i in range(tag_length):
                    concatted.append(0x00)

            else:
                msg = '! Unknown PDOL Tag %s' % tag
                logging.info(msg)
                raise Exception(msg)

        data.append(len(concatted))
        data.extend(concatted)

    ret_data, sw1, sw2 = select_and_requery(connection=connection,
                                            cla=GET_PROCESSING_OPTIONS.cla,
                                            ins=GET_PROCESSING_OPTIONS.ins,
                                            p1=0x00,
                                            p2=0x00,
                                            data=data,
                                            le=0x00)

    #    if DO_LOG:
    #        logging.info('\n' + 'GET PROCESSING OPTIONS - REQUEST PDOL')
    #        for x in report_on_reply(sw1, sw2, ret_data):
    #            logging.info(x)

    # 0x77 0x16 0x82 0x02 0x38 0x00 0x94 0x10 0x08 0x01 0x02 0x00 0x10 0x01 0x02 0x00 0x18 0x01 0x02 0x01 0x20 0x01 0x02 0x00
    # 77 = Format 2 Type Response
    # 77 16 82023800941008010200100102001801020120010200
    # 82 = AIP = Application Interchange Profile
    # 82 02 3800
    # 94 = AFL = Application File Locator
    # 94 10 08010200100102001801020120010200
    #
    # AFL = 08 01 02 00
    #       10 01 02 00
    #       18 01 02 01
    #       20 01 02 00
    #                      SFI 1st Last OMA-Involved
    # 08 = 8  => 00001000 => 1  01   02           00
    # 10 = 16 => 00010000 => 2  01   02           00
    # 18 = 24 => 00011000 => 3  01   02           01
    # 20 = 32 => 00100000 => 4  01   02           00

    get_proc_options_format_1_tags = ['80']
    get_proc_options_format_2_tags = ['77', '82', '94']

    combined_tags = []
    combined_tags.extend(get_proc_options_format_1_tags)
    combined_tags.extend(get_proc_options_format_2_tags)
    '''
    hex_string = bit_tools.byte_list_to_hex_string(ret_data)
    file = open('c:/dev/logs/pdol.txt', 'w')
    file.write(hex_string + '\n')
    file.close()
    '''

    tlv_tree = tlv_utils.parse_tlv(ret_data, known_tags=combined_tags)

    afl = None

    # FORMAT 1 - Visa
    if (get_proc_options_format_1_tags[0] in tlv_tree.distinct_tag_list()):
        node = tlv_tree.get_nodes_for_qtag('80')[0]
        aip_afl = node.value_byte_list
        aip_length = 2
        aip = aip_afl[0:aip_length]
        afl = aip_afl[aip_length:]

#        if DO_LOG:
#            logging.info('AIP_AFL = ' + '.'.join(['%02X' % b for b in aip_afl]))
#            logging.info('AIP     = ' + '.'.join(['%02X' % b for b in aip]))
#            logging.info('AFL     = ' + '.'.join(['%02X' % b for b in afl]))

# FORMAT 2 - MasterCard
    else:
        node = tlv_tree.get_nodes_for_qtag('77.94')[0]
        afl = node.value_byte_list
        node = tlv_tree.get_nodes_for_qtag('77.82')[0]
        aip = node.value_byte_list


#    if DO_LOG:
#        logging.info('')
#        for line in tlv_tree.report():
#            logging.info(line)
#
    return afl, aip