예제 #1
0
 def _display_key_info(self, cps):
     keys = ['8000', 'A006', '8401', '9000']
     dgis = cps.get_all_dgis()
     Log.info(
         '===================== First Application Key Info ====================='
     )
     for dgi in dgis:
         kcv = ''
         for tag, value in dgi.get_all_tags().items():
             if tag in keys:
                 if tag != '9000':
                     kcv = algorithm.gen_kcv(value)
                 Log.info('tag%-5s:       value:%s  kcv:%s', tag, value,
                          kcv)
     second_keys = ['8000_2', '9000_2']
     Log.info(
         '\n===================== Second Application Key Info ====================='
     )
     for dgi in dgis:
         kcv = ''
         for tag, value in dgi.get_all_tags().items():
             if dgi.name in second_keys:
                 Log.info('tag%-5s:       value:%s  kcv:%s', tag, value,
                          kcv)
     Log.info('\n')
def check_fci_9102(buffer):
    tlvs = utils.parse_tlv(buffer)
    sub_tlvs = []
    sub_fci_9102 = []
    for tlv in tlvs:
        for fci_item in fci_9102:
            if tlv.tag == fci_item[0]:
                sub_fci_9102.append(fci_item)
                sub_tlvs.append(tlv)
    # 判断集合中的顺序是否一致
    has_ordered = True
    for index in range(len(sub_fci_9102)):
        if sub_fci_9102[index][0] != sub_tlvs[index].tag or sub_fci_9102[index][1] != sub_tlvs[index].level:
            Log.warn('tag%s is not ordered.',sub_tlvs[index].tag)
            has_ordered = False
    if not has_ordered:
        order_tags = [item[0] for item in sub_fci_9102]
        Log.warn('the minium order list should be %s',str(order_tags))
    # 判断是否缺少必须的tag
    for item in fci_9102:
        if item not in sub_fci_9102:
            if item[2] == TagCondition.M:
                Log.error('FCI 9102 should contains tag%s',item[0])
            elif item[2] == TagCondition.C:
                Log.warn('FCI 9102 recommand that tag%s should be existed.',item[0])
    # 判断是否包含多余的tag
    for item in tlvs:
        if item not in sub_tlvs:
            Log.warn('FCI 9102 should not contains tag%s',item.tag)
예제 #3
0
 def read_log(self):
     Log.info('get trans log')
     tag9F4D = self.get_tag(PROCESS_STEP.SELECT, '9F4D')
     if not tag9F4D:
         Log.info('no tag9F4D,do not support record log')
     else:
         record_count = int(tag9F4D[2:4], 16)
         log_sfi = int(tag9F4D[0:2], 16)
         buffer = []
         for i in range(record_count + 1):
             resp = apdu.read_record(log_sfi, i + 1, (0x9000, 0x6A83))
             if resp.sw == 0x9000:
                 Log.info(resp.response)
                 buffer.append(resp.response)
             else:
                 break
         Log.info('%-10s%-15s%-10s%-10s%-8s%-15s%-10s%-10s%-10s', 'result',
                  'money', 'currency', 'date', 'atc', 'cvr', 'interface',
                  'time', 'merchant')
         for resp in buffer:
             result = resp[0:2]
             money = resp[2:14]
             currency = resp[14:18]
             date = resp[18:24]
             atc = resp[24:28]
             cvr = resp[28:40]
             interface = resp[40:42]
             trans_time = resp[42:48]
             merchant = utils.bcd_to_str(resp[48:])
             Log.info('%-10s%-15s%-10s%-10s%-8s%-15s%-10s%-10s%-10s',
                      result, money, currency, date, atc, cvr, interface,
                      trans_time, merchant)
예제 #4
0
def get_dgi_list(fh):
    dgi_list_len = fh.read_int(fh.current_offset)
    dgi_list_str = fh.read_binary(fh.current_offset, dgi_list_len)
    dgi_list = []
    for i in range(0, dgi_list_len * 2, 4):
        dgi_list.append(dgi_list_str[i:i + 4])

    des_encrypt_dgi_list_len = fh.read_int(fh.current_offset)
    des_encrypt_dgi_list_str = fh.read_binary(fh.current_offset,
                                              des_encrypt_dgi_list_len)
    des_encrypt_dgi_list = []
    for i in range(0, des_encrypt_dgi_list_len * 2, 4):
        des_encrypt_dgi_list.append(des_encrypt_dgi_list_str[i:i + 4])

    sm_encrypt_dgi_list_len = fh.read_int(fh.current_offset)
    sm_encrypt_dgi_list_str = fh.read_binary(fh.current_offset,
                                             sm_encrypt_dgi_list_len)
    sm_encrypt_dgi_list = []
    for i in range(0, sm_encrypt_dgi_list_len * 2, 4):
        sm_encrypt_dgi_list.append(sm_encrypt_dgi_list_str[i:i + 4])
    Log.info('sm encrypt dgi list: ', end=' ')
    Log.info(sm_encrypt_dgi_list)
    des_encrypt_dgi_list.extend(sm_encrypt_dgi_list)
    log_dgi_list_len = fh.read_int(fh.current_offset)
    fh.read_binary(fh.current_offset, log_dgi_list_len)  #暂时不需要log DGI记录
    return dgi_list, des_encrypt_dgi_list
예제 #5
0
 def second_gac(self):
     tag8D = self.get_tag(PROCESS_STEP.READ_RECORD, '8D')
     data = tools.assemble_dol(tag8D)
     resp = super().gac(Crypto_Type.TC, data)
     if resp.sw != 0x9000:
         Log.info('send gac1 failed.')
         return
     return resp
예제 #6
0
 def create_check_aid_case(self, check_aid_list):
     case_node = self.smart_qc.create_case_node('AID检测-非接',
                                                'SSQCaseEx3.dll')
     # <DeviceList>
     device_list_node = self.smart_qc.create_node(case_node, 'DeviceList')
     self.smart_qc.create_device_node(device_list_node, 'PC Twin2')
     # <SpecialInput>
     special_input_node = self.smart_qc.create_node(case_node,
                                                    'SpecialInput')
     # <CardStruct>
     card_struct_node = self.smart_qc.create_node(special_input_node,
                                                  'CardSturct')
     # <MF>
     self.smart_qc.create_node(card_struct_node, 'MF', fid='3F00')
     # <ApduList>
     app_nodes = self.dp_xml_handle.get_child_nodes(
         self.dp_xml_handle.root_element, 'App')
     cur_aids = []
     for app_node in app_nodes:
         aid = self.dp_xml_handle.get_attribute(app_node, 'aid')
         if not aid:
             Log.error(
                 'can not get aid from dp xml, check wether the dp xml is correct.'
             )
             return
         cur_aids.append(aid)
     need_check_aids = []
     for aid in check_aid_list:
         if aid not in cur_aids:
             need_check_aids.append(aid)
     apdu_list_node = self.smart_qc.create_node(card_struct_node,
                                                'ApduList')
     for aid in need_check_aids:
         apdu = '00A40400' + utils.get_strlen(aid) + aid
         self.smart_qc.create_node(apdu_list_node,
                                   'Apdu ',
                                   value=apdu,
                                   sw12="6A82")
     test_process_list_node = self.smart_qc.create_node(
         case_node, 'TestProcessList')
     self.smart_qc.create_node(test_process_list_node,
                               'Card_sturct_test',
                               enable='false')
     self.smart_qc.create_node(test_process_list_node,
                               'Compare_IC_info',
                               enable='false')
     self.smart_qc.create_node(test_process_list_node,
                               'Special_file_test',
                               enable='false')
     self.smart_qc.create_node(test_process_list_node,
                               'Transaction_test',
                               enable='false')
     self.smart_qc.create_node(test_process_list_node,
                               'Check_atr',
                               enable='false')
     self.smart_qc.create_node(test_process_list_node,
                               'ApduList_test',
                               enable='true')
예제 #7
0
def check_startswith_70(apdu_resps):
    '''
    检测读记录响应数据是否以70模板开头
    '''
    for resp in apdu_resps:
        if helper.case_startswith('70', resp.response) != CR.OK:
            Log.error('read record response not start with template 70')
            return CR.ERROR
    return CR.OK
예제 #8
0
 def store_tag(self,step,tag,value):
     '''
     存储交易中的tag信息
     '''
     if not value:
         Log.warn('tag:%s is empty')
     if tag == '9F10':
         self.dki = value[2:4]
         self.cvn = value[4:6]
     self.tags_info.append(TransTag(step,tag,value))
예제 #9
0
def check_empty_tag(trans_obj):
    '''
    检测读记录之前的数据是否有空值的现象
    '''
    has_empty_tag = False
    for tag_info in trans_obj.tags_info:
        if not tag_info.value:
            Log.error('tag%s is empty', tag_info.tag)
            has_empty_tag = True
    if has_empty_tag:
        return CR.ERROR
    return CR.OK
예제 #10
0
 def store_tag_group(self,step,tlvs):
     '''
     存储交易中的一组tag信息
     '''
     for tlv in tlvs:
         if not tlv.is_template:
             if not tlv.value:
                 Log.warn('tag:%s is empty',tlv.tag)
             if tlv.tag == '9F10':
                 self.dki = tlv.value[2:4]
                 self.cvn = tlv.value[4:6]
             self.tags_info.append(TransTag(step,tlv.tag,tlv.value))
예제 #11
0
 def second_gac(self):
     tag8D = self.get_tag(PROCESS_STEP.READ_RECORD, '8D')
     data = tools.assemble_dol(tag8D)
     resp = super().gac(Crypto_Type.TC, data)
     if resp.sw != 0x9000:
         Log.info('send gac1 failed.')
         return
     tlvs = utils.parse_tlv(resp.response)
     tools.output_apdu_info(resp)
     self.store_tag_group(PROCESS_STEP.SECOND_GAC,
                          utils.parse_tlv(resp.response))
     return resp
예제 #12
0
 def _filter(self, data):
     if data and data.startswith('APDU'):
         start_index = data.find('[')
         end_index = data.find(']', start_index)
         resp_start_index = data.find('[', end_index)
         resp_end_index = data.find(']', resp_start_index)
         req = data[start_index + 1:end_index]  #取[]中间的APDU指令
         resp = data[resp_start_index + 1:resp_end_index]
         if req[0:4] in ('00A4', '80E2', '80E6', '80D8', '80F0'):
             if not req.endswith('00'):
                 Log.error('data error: %s not end with 00' % data)
             return req[0:-2], resp
     return '', ''
예제 #13
0
 def first_gac(self):
     tag8C = self.get_tag(PROCESS_STEP.READ_RECORD, '8C')
     data = tools.assemble_dol(tag8C)
     resp = super().gac(Crypto_Type.ARQC, data)
     if resp.sw != 0x9000:
         Log.info('send gac1 failed.')
         return
     tlvs = utils.parse_tlv(resp.response)
     tools.output_apdu_info(resp)
     self.store_tag_group(PROCESS_STEP.FIRST_GAC,
                          utils.parse_tlv(resp.response))
     self.run_case('case_first_gac', 'run_mc', resp)
     return resp
예제 #14
0
 def _comapre_dgi_list(self, mock_cps, prod_cps):
     Log.info('===================== Check DGI List =====================')
     mock_cps_dgis = [item.name for item in mock_cps.dgi_list]
     prod_cps_dgis = [item.name for item in prod_cps.dgi_list]
     for mock_cps_dgi_name in mock_cps_dgis:
         if mock_cps_dgi_name not in prod_cps_dgis:
             Log.error('should perso DGI %s in product environment',
                       mock_cps_dgi_name)
     for prod_cps_dgi_name in prod_cps_dgis:
         if prod_cps_dgi_name not in mock_cps_dgis:
             Log.error('should NOT perso DGI %s in product environment',
                       prod_cps_dgi_name)
     Log.info("\nmock dgi list:%s\n", mock_cps_dgis)
     Log.info('prod dgi list:%s\n', str(prod_cps_dgis))
예제 #15
0
def process_card_data(fh, rule_file):
    cps = Cps()
    flag = fh.read_str(fh.current_offset, 6)
    if flag != '000EMV':
        return False, cps
    card_data_len = fh.read_int64(fh.current_offset)
    app_count = utils.hex_str_to_int(fh.read_binary(fh.current_offset, 1))
    for app in range(app_count):
        aid_len = utils.hex_str_to_int(fh.read_binary(fh.current_offset, 1))
        aid = fh.read_binary(fh.current_offset, aid_len)
        app_data_len = fh.read_int64(fh.current_offset)
        dgi_list, encrypt_dgi_list = get_dgi_list(fh)
        Log.info('encrypt dgi list :', encrypt_dgi_list)
        for item in dgi_list:
            card_dgi = Dgi()
            dgi = fh.read_binary(fh.current_offset, 2)
            dgi_len = utils.hex_str_to_int(fh.read_binary(
                fh.current_offset, 1))
            dgi_data = fh.read_binary(fh.current_offset, dgi_len)
            n_dgi = utils.hex_str_to_int(dgi)
            card_dgi.dgi = dgi
            if dgi == '0098' or dgi == '0099':
                dgi = process_pse(dgi, dgi_data)
            elif dgi == '0100':
                dgi = process_ppse(dgi, dgi_data)
            else:
                if n_dgi < 0x0B01:
                    if dgi_data[0:2] != '70':
                        return False, cps
                    if dgi_data[2:4] == '81':
                        dgi_data = dgi_data[6:]
                    else:
                        dgi_data = dgi_data[4:]
                if utils.is_rsa(dgi) is False and utils.is_tlv(dgi_data):
                    tlvs = utils.parse_tlv(dgi_data)
                    if len(tlvs) > 0 and tlvs[0].is_template is True:
                        value = utils.assemble_tlv(tlvs[0].tag, tlvs[0].value)
                        card_dgi.add_tag_value(dgi, value)
                    else:
                        for tlv in tlvs:
                            value = process_tag_decrypt(
                                rule_file, tlv.tag, tlv.value)
                            value = utils.assemble_tlv(tlv.tag, value)
                            card_dgi.add_tag_value(tlv.tag, value)
                else:
                    card_dgi.add_tag_value(dgi, dgi_data)
            cps.add_dgi(card_dgi)
    return True, cps
예제 #16
0
 def first_gac(self):
     tag8C = self.get_tag(PROCESS_STEP.READ_RECORD, '8C')
     data = tools.assemble_dol(tag8C)
     resp = super().gac(Crypto_Type.ARQC, data)
     if resp.sw != 0x9000:
         Log.info('send gac1 failed.')
         return
     tlvs = utils.parse_tlv(resp.response)
     if len(tlvs) != 1 and tlvs[0].tag != '80':
         Log.info('gac1 response data error')
     data = tlvs[0].value
     self.store_tag(PROCESS_STEP.FIRST_GAC, '9F27', data[0:2])
     self.store_tag(PROCESS_STEP.FIRST_GAC, '9F36', data[2:6])
     self.store_tag(PROCESS_STEP.FIRST_GAC, '9F26', data[6:22])
     self.store_tag(PROCESS_STEP.FIRST_GAC, '9F10', data[22:])
     return resp
예제 #17
0
 def _display_dki(self, cps):
     dgis = cps.get_all_dgis()
     Log.info(
         '===================== First Application DKI Info ====================='
     )
     for dgi in dgis:
         for tag, value in dgi.get_all_tags().items():
             if tag in ('9F10') and '_2' not in dgi.name:
                 Log.info('tag9F10:%s       DKI:%s', value[6:], value[8:10])
     Log.info(
         '\n===================== Second Application DKI Info ====================='
     )
     for dgi in dgis:
         for tag, value in dgi.get_all_tags().items():
             if tag in ('9F10') and '_2' in dgi.name:
                 Log.info('tag9F10:%s       DKI:%s', value[6:], value[8:10])
     Log.info('\n')
예제 #18
0
 def read_record(self,tag94):
     '''
     读记录数据
     '''
     resps = []
     afls = utils.parse_afl(tag94)
     for afl in afls:
         Log.info('read record: %02X%02X',afl.sfi,afl.record_no)
         resp = apdu.read_record(afl.sfi,afl.record_no)
         if resp.sw != 0x9000:
             Log.error('read record wrong')
             return resps
         tools.output_apdu_info(resp)
         resps.append(resp)
         if afl.is_static_sign_data:
             self.sig_data += utils.remove_template70(resp.response)
     return resps
예제 #19
0
 def _parse_set_status_cmd(self, req, resp):
     if req[0:6] == '80F080':
         if req[6:8] == '07':
             Log.info('current card lifecycle: OP_INITIALIZE')
         elif req[6:8] == '0F':
             Log.info('current card lifecycle: SECURED')
         else:
             Log.error('Unknown card lifecycle')
         if resp != '9000':
             Log.error('set current lifecyle Failed.')
예제 #20
0
def check_duplicate_tag(trans_obj):
    '''
    检测GPO和读记录数据中是否有重复tag出现
    '''
    tags = []
    has_duplicate = False
    for tag_info in trans_obj.tags_info:
        if tag_info.step in (PROCESS_STEP.GPO, PROCESS_STEP.READ_RECORD):
            tags.append(tag_info.tag)
    tag_counts = len(tags)
    for current in range(tag_counts):
        for index in range(current + 1, tag_counts):
            if tags[current] == tags[index]:
                Log.error('tag%s has duplicated', tags[current])
                has_duplicate = True
    if has_duplicate:
        return CR.ERROR
    return CR.OK
예제 #21
0
def send_raw(cmd, resp_sw_list=None):
    '''
    在连接读卡器后,发送APDU指令。
    cmd 表示要发送的APDU命令,包括命令头,数据长度,数据。
    resp_sw_list 表示期望的响应返回码列表,若返回不是期望的响应码,则自动退出APDU的交互
    '''
    apdu_response = ApduResponse()
    bytes_cmd = str.encode(cmd)
    resp_len = c_int(2048)
    resp_data = create_string_buffer(resp_len.value)
    Log.info('APDU: %s', cmd)
    apdu_response.sw = _pcsc_lib.SendApdu(bytes_cmd, resp_data, resp_len)
    apdu_response.response = bytes.decode(resp_data.value)
    apdu_response.request = cmd
    Log.info('RESP: %X', apdu_response.sw)
    if resp_sw_list and apdu_response.sw not in resp_sw_list:
        sys.exit(1)
    return apdu_response
예제 #22
0
 def create_tag_node(self,
                     app_name,
                     dp_dgi_node,
                     compare_node,
                     aid,
                     super_tag_list=[]):
     comment = app_name
     comment += '_' + self.dp_xml_handle.get_attribute(dp_dgi_node,
                                                       'name') + ' tag '
     tag_nodes = self.dp_xml_handle.get_nodes(dp_dgi_node, 'Tag')
     for tag_node in tag_nodes:
         name = self.dp_xml_handle.get_attribute(tag_node, 'name')
         if name != '--':
             comment += name + '/'
     # comment node
     self.smart_qc.create_comment_node(compare_node, comment)
     # tag node
     for tag_node in tag_nodes:
         name = self.dp_xml_handle.get_attribute(tag_node, 'name')
         value = self.dp_xml_handle.get_attribute(tag_node, 'value')
         source = self.dp_xml_handle.get_attribute(tag_node, 'type')
         if source == 'kms':
             continue
         if super_tag_list:
             existed = False
             for item in super_tag_list:
                 if item[0] == name:
                     existed = True
                     item[1] = True
                     break
             if not existed:
                 Log.warn(
                     'tag %s not be checked in smartQC xml, maybe you need config this tag in your "get_data_list" configration',
                     name)
                 continue
         if source == 'fixed':
             self.smart_qc.create_tag_node(
                 compare_node, name, value,
                 settings.get_mappings_info(aid, name).desc, 'BCD', 'error')
         elif source == 'file':
             _, value = self.mock_cps._parse_tag_value(tag_node)
             self.smart_qc.create_tag_node(
                 compare_node, name, value,
                 settings.get_mappings_info(aid, name).desc, 'BCD', 'warn')
예제 #23
0
def check_tag_len(trans_obj):
    has_error = False
    for tag_info in trans_obj.tags_info:
        tag_len = len(tag_info.value) // 2
        len_type, lens = get_tag_len(tag_info.tag, trans_obj.aid)
        if len_type == LenType.Range:
            if tag_len < lens[0] or tag_len > lens[1]:
                Log.error(
                    'tag%s length is not correct, should be in range%d-%d. current len: %d',
                    tag_info.tag, lens[0], lens[1], tag_len)
                has_error = True
        elif len_type == LenType.Fixed:
            if tag_len not in lens:
                Log.error(
                    'tag%s length is not correct, should be any of %s. current len: %d',
                    tag_info.tag, str(lens), tag_len)
                has_error = True
    if has_error:
        return CR.ERROR
    return CR.OK
예제 #24
0
 def first_gac_cda(self):
     tag8C = self.get_tag(PROCESS_STEP.READ_RECORD, '8C')
     if not tag8C:
         Log.error('first gac cda faild since tag8C is tempty')
         return False
     tls = utils.parse_tl(tag8C)
     data = ''
     self.unpredicatble_number = ''
     for tl in tls:
         data += terminal.get_terminal(tl.tag, tl.len)
         if tl.tag == '9F37':
             self.unpredicatble_number = terminal.get_terminal(
                 tl.tag, tl.len)
     resp = super().gac(Crypto_Type.TC_CDA, data)
     if resp.sw != 0x9000:
         Log.error('send first gac command failed. SW:%04X', resp.sw)
         return
     tlvs = utils.parse_tlv(resp.response)
     tools.output_apdu_info(resp)
     self.store_tag_group(PROCESS_STEP.FIRST_GAC, tlvs)
예제 #25
0
def get_pse_and_ppse_dgi_list(sddf_dgi_list):
    global _aid_list_info
    pse_dgi_list = []
    ppse_dgi_list = []
    pse_index, _ = _aid_list_info.get(
        '315041592E5359532E4444463031',
        ('F', ''))  #_aid_list_info['315041592E5359532E4444463031']
    ppse_index, _ = _aid_list_info.get(
        '325041592E5359532E4444463031',
        ('F', ''))  #_aid_list_info['325041592E5359532E4444463031']
    if pse_index == 'F':
        Log.error('无法获取PSE DGI相关列表')
    if ppse_index == 'F':
        Log.error('无法获取PPSE DGI相关列表')
    for dgi in sddf_dgi_list:
        if dgi[4] == pse_index:
            pse_dgi_list.append(dgi)
        elif dgi[4] == ppse_index:
            ppse_dgi_list.append(dgi)
    return pse_dgi_list, ppse_dgi_list
예제 #26
0
def _parse_tlv(dgi_name, data):
    dgi = Dgi()
    data = utils.remove_dgi(data, dgi_name)
    int_dgi = utils.str_to_int(dgi_name)
    if int_dgi < 0x0B01:
        if data[0:2] != '70':
            Log.error('数据有误,小于0B01的DGI应包含70模板')
            return None
        data = utils.remove_template70(data)
    if not utils.is_rsa(dgi_name) and utils.is_tlv(data):
        tlvs = utils.parse_tlv(data)
        if len(tlvs) > 0 and tlvs[0].is_template is True:
            value = utils.assemble_tlv(tlvs[0].tag, tlvs[0].value)
            dgi.add_tag_value(dgi_name, value)
        else:
            for tlv in tlvs:
                value = utils.assemble_tlv(tlv.tag, tlv.value)
                dgi.add_tag_value(tlv.tag, value)
    else:
        dgi.add_tag_value(dgi_name, data)
    return dgi
예제 #27
0
 def issuer_auth(self):
     tag9F26 = self.get_tag(PROCESS_STEP.FIRST_GAC, '9F26')
     if not self.cvn:
         Log.error('can not get CVN, check tag9F10 wether existed.')
         return
     if self.cvn == '0A':  # CVN10处理流程
         arc = '3030'
         key = self.key_ac
         if self.key_flag == App_Master_Key.MDK:
             tag5A = self.get_tag(PROCESS_STEP.READ_RECORD, '5A')
             tag5F34 = self.get_tag(PROCESS_STEP.READ_RECORD, '5F34')
             key = auth.gen_udk(key, tag5A, tag5F34)
         arpc = auth.gen_arpc_by_des3(key, tag9F26, arc)
         resp = apdu.external_auth(arpc, arc)
         if resp.sw == 0x9000:
             return True
     elif self.cvn == '12':  # CVN18处理流程
         csu = '00820000'
         self.divert_key()  #需要使用AC session key
         arpc = auth.gen_arpc_by_mac(self.session_key_ac, tag9F26, csu)
         terminal.set_terminal('91', arpc + csu)
         return True
     return False
예제 #28
0
def process_mag_data(fh,rule_file_name):
    rule_file = RuleXml(rule_file_name)
    mag_node = rule_file.get_first_node(rule_file.root_element,'Magstrip')
    
    mag_flag = fh.read_str(fh.current_offset,6)
    if mag_flag != '000MAG':
        return False
    mag_data_len = fh.read_int64(fh.current_offset)
    track_flag_list = []
    track_flag_list.append(fh.read(fh.current_offset,1))
    track_flag_list.append(fh.read(fh.current_offset + 1,1))
    track_flag_list.append(fh.read(fh.current_offset + 1,1))
    mag_data = fh.read_binary(fh.current_offset,mag_data_len - 5)
    mag_data_list = [x for x in mag_data.split('7C') if len(x) > 0]
    Log.info('decrypt mag data: ',end='')
    Log.info(mag_data_list)
    dgi = Dgi()
    dgi.name = 'Magstrip'
    if mag_node is not None:
        mag_key = rule_file.get_attribute(mag_node,'key')
        decrypt_mag_list = []
        for data in mag_data_list:
            data = utils.bcd_to_str(data)
            data = algorithm.des3_ecb_decrypt(mag_key,data)
            data = utils.bcd_to_str(data)
            data_len = int(data[0:4])
            data = data[4:data_len + 4].rstrip()
            decrypt_mag_list.append(data)
        pos = 1
        for mag in decrypt_mag_list:
            for index in range(pos,4):
                pos += 1
                option = 'mag' + str(pos)
                if track_flag_list[index - 1] == '0':
                    dgi.add_tag_value(option,'')
                    continue
                dgi.add_tag_value(option,mag)
                break
        Log.info('decrypt mag data: ',end='')
        Log.info(decrypt_mag_list)
    return dgi
예제 #29
0
def split_rsa(xml, goldpac_dgi_list, is_second_app):
    rule_file_handle = RuleXml(xml.file_name)
    _, key = rule_file_handle.get_decrypted_attribute('RSA')
    sddf_tag = ''
    _, sddf_tag, _ = rule_file_handle.get_tag_link_attribute(
        'EMVDataName', 'Icc_KeyPair')
    if is_second_app:
        sddf_tag = sddf_tag[0:4] + get_second_app_index() + sddf_tag[5:8]
    else:
        sddf_tag = sddf_tag[0:4] + get_first_app_index() + sddf_tag[5:8]
    encrypted_data = get_goldpac_data(goldpac_dgi_list, sddf_tag,
                                      is_second_app)
    if encrypted_data is None:
        Log.error('无法获取RSA数据[tag' + sddf_tag + ']缺少数据')
    decrypted_data = algorithm.des3_ecb_decrypt(key, encrypted_data)
    if len(decrypted_data) <= 2 or decrypted_data[0:2] != '30':
        Log.error('RSA解密失败')
        return None
    decrypted_data = decrypted_data[2:]
    _, decrypted_data = get_rsa_dgi_len(decrypted_data)
    dgi_list = []
    for i in range(9):
        decrypted_data = decrypted_data[2:]  #remove flag '02'
        dgi_len, decrypted_data = get_rsa_dgi_len(decrypted_data)
        dgi_data = get_rsa_dgi_value(decrypted_data, dgi_len)
        decrypted_data = decrypted_data[dgi_len:]
        dgi = Dgi()
        if is_second_app:
            dgi.name = '_2'
        if i == 4:
            dgi.name = '8205' + dgi.name
        elif i == 5:
            dgi.name = '8204' + dgi.name
        elif i == 6:
            dgi.name = '8203' + dgi.name
        elif i == 7:
            dgi.name = '8202' + dgi.name
        elif i == 8:
            dgi.name = '8201' + dgi.name
        else:
            continue
        dgi.add_tag_value(dgi.name[0:4], dgi_data)
        dgi_list.append(dgi)
        Log.info(dgi.name[0:4] + '=' + dgi_data)
    return dgi_list
예제 #30
0
def get_terminal(tag, length=None, default=None):
    value = terminal_cfg.get(tag)
    if not value:
        if length:
            value = '0' * length * 2
        Log.warn('can not require terminal settings for tag %s', tag)
        if value:
            Log.warn('set tag%s value:%s', tag, value)
            return value
        return default
    else:
        if length and len(value) != length * 2:
            if len(value) >= length * 2:
                value = value[0:length * 2]
            else:
                value += '0' * (length * 2 - len(value))
                Log.warn('padding 0 at tag %s', tag)
    return value