def process_data(data,data_type): dgi = Dgi() dgi.name = data_type item_list = process_tlv(data) for item in item_list: dgi.add_tag_value(item[0],item[2]) return dgi
def process_add_fixed_tag(self, dgi_name, tag, value, before_tag, after_tag): dgis = self.cps.get_all_dgis() dgi_names = [dgi.name for dgi in dgis] if dgi_name not in dgi_names: new_dgi = Dgi() new_dgi.name = dgi_name new_dgi.add_tag_value(tag, value) self.cps.add_dgi(new_dgi) else: for item in self.cps.dgi_list: if item.name == dgi_name: if tag in item.tag_value_dict: old_value = item.get_value(tag) new_value = old_value[len(tag) + 2:] + value new_value = tag + utils.get_strlen( new_value) + new_value item.modify_value(tag, new_value) else: if before_tag is not '': item.insert_before(before_tag, tag, value) elif after_tag is not '': item.insert_after(after_tag, tag, value) else: item.add_tag_value(tag, value) return self.cps
def get_cps(cps_file): ''' 通过cps文件获取cps数据 ''' cps = Cps() ini = IniParser(cps_file) sections = ini.get_sections() for section in sections: if section == 'AID_LIST': value = ini.get_value(section,section) aid_list = value.split(';') cps.pse_aid = aid_list[0] cps.ppse_aid = aid_list[1] cps.first_app_aid = aid_list[2] cps.second_app_aid = aid_list[3] elif section in ('DGI_LIST','DGI_LIST_2'): continue else: dgi = Dgi() dgi.name = section options = ini.get_options(section) for option in options: value = ini.get_value(section,option) dgi.add_tag_value(option,value) cps.add_dgi(dgi) return cps
def process_rule_eps(rule_file_name, cps): key = '0123456789ABCDEF1111111111111111' #默认解密key rule_handle = RuleXml(rule_file_name) handle8020_node = rule_handle.get_first_node(rule_handle.root_element, 'Handle8020') if not handle8020_node: return cps key = rule_handle.get_attribute(handle8020_node, 'key') for dgi_item in cps.dgi_list: if dgi_item.name == '8020': tag8020 = '' tagA001 = '' value = dgi_item.get_value('8020') dgi_len = len(value) for i in range(0, dgi_len, 34): tagA001 += value[i:i + 2] + '010000FF0000' data = algorithm.des3_ecb_decrypt(key, value[i + 2:i + 34]) tag8020 += data dgi_item.modify_value('8020', tag8020) dgiA001 = Dgi() dgiA001.name = 'A001' dgiA001.add_tag_value('A001', tagA001) cps.add_dgi(dgiA001) if dgi_item.name == '9020': tag9020 = '' value = dgi_item.get_value('9020') for i in range(0, len(value), 8): tag9020 += value[i + 2:i + 8] dgi_item.modify_value('9020', tag9020) return cps
def process_add_tag(self, src_dgi, src_tag, dst_dgi, dst_tag): dst_tag_value = self._get_tag_value(dst_dgi, dst_tag) dgi = Dgi() dgi.name = src_dgi dgi.add_tag_value(src_tag, dst_tag_value) self.cps.add_dgi(dgi) return self.cps
def _assemble_dgi(self, dgi_name, tlvs): dgi = Dgi() dgi.name = dgi_name for tlv in tlvs: if not tlv.is_template: value = utils.assemble_tlv(tlv.tag, tlv.value) #组装为TLV结构 dgi.add_tag_value(tlv.tag, value) return dgi
def parse_A006(xml, goldpac_dgi_list): sddf_A006 = get_sddf_tag(xml, 'EMVDataName', 'Kidn') dgi = Dgi() dgi.name = 'A006' data = get_goldpac_data(goldpac_dgi_list, sddf_A006, False) rule_file_handle = RuleXml(xml.file_name) _, key = rule_file_handle.get_decrypted_attribute('A006') #顺带解密 data = algorithm.des3_ecb_decrypt(key, data) dgi.add_tag_value(dgi.name, data) return dgi
def process_jetco_special_dgi(xml, goldpac_dgi_list, cps): rule_file_handle = RuleXml(xml.file_name) add_tag_nodes = xml.get_nodes(xml.root_element, 'AddTag') for node in add_tag_nodes: attrs = xml.get_attributes(node) dgi = Dgi() dgi.name = attrs['srcDGI'] if 'srcTag' not in attrs: attrs['srcTag'] = attrs['dstTag'] data = '' is_second_app = False if '_2' in dgi.name: is_second_app = True # 对DF20,DF27做特殊处理 if attrs['dstDGI'] == 'DF20': _, sddf_tag_DF18, _ = rule_file_handle.get_tag_link_attribute( 'EMVTag', 'DF18') _, sddf_tag_DF19, _ = rule_file_handle.get_tag_link_attribute( 'EMVTag', 'DF19') data_DF18 = get_goldpac_data(goldpac_dgi_list, sddf_tag_DF18, is_second_app) data_DF19 = get_goldpac_data(goldpac_dgi_list, sddf_tag_DF19, is_second_app) data = data_DF18 + data_DF19 data = data[0:data.find('20')] data = utils.bcd_to_str(data) if len(data) // 2 > 0x7F: data = attrs['dstDGI'] + '81' + utils.get_strlen(data) + data else: data = attrs['dstDGI'] + utils.get_strlen(data) + data elif attrs['dstDGI'] == 'DF27': _, sddf_tag_DF16, _ = rule_file_handle.get_tag_link_attribute( 'EMVTag', 'DF16') _, sddf_tag_DF17, _ = rule_file_handle.get_tag_link_attribute( 'EMVTag', 'DF17') data_DF16 = get_goldpac_data(goldpac_dgi_list, sddf_tag_DF16, is_second_app) data_DF17 = get_goldpac_data(goldpac_dgi_list, sddf_tag_DF17, is_second_app) data = data_DF16 + data_DF17 data = data[0:data.find('20')] data = utils.bcd_to_str(data) if len(data) // 2 > 0x7F: data = attrs['dstDGI'] + '81' + utils.get_strlen(data) + data else: data = attrs['dstDGI'] + utils.get_strlen(data) + data else: _, sddf_tag, _ = rule_file_handle.get_tag_link_attribute( 'EMVTag', attrs['dstTag']) data = get_goldpac_data(goldpac_dgi_list, sddf_tag, is_second_app) dgi.add_tag_value(attrs['srcTag'], data) cps.add_dgi(dgi) return cps
def parse_pse_and_ppse(xml, pse_dgi_list, ppse_dgi_list, goldpac_dgi_list): pse_dgi = Dgi() pse_dgi.name = 'PSE' ppse_dgi = Dgi() ppse_dgi.name = 'PPSE' for sddf_tag in pse_dgi_list: tag, value = parse_pse_and_ppse_data(xml, sddf_tag, goldpac_dgi_list) pse_dgi.add_tag_value(tag, value) for sddf_tag in ppse_dgi_list: tag, value = parse_pse_and_ppse_data(xml, sddf_tag, goldpac_dgi_list) ppse_dgi.add_tag_value(tag, value) return pse_dgi, ppse_dgi
def process_dp(dp_file, rule_file): fh = FileHandle(dp_file, 'rb+') fh.read(fh.current_offset, 8596) #reserved dgi_list = get_dgi_list(fh) file_size = fh.file_size cps_list = [] while fh.current_offset < file_size: card_seq = fh.read_int64_reverse(fh.current_offset) card_data_total_len = fh.read_int_reverse(fh.current_offset) cps = Cps() #存储单个卡片数据 cps.dp_file_path = dp_file pse_and_ppse_dgi = [ 'Store_PSE_1', 'Store_PSE_2', 'Store_PPSE', 'DGIF001' ] for dgi_name in dgi_list: dgi = Dgi() #存储单个DGI数据 if dgi_name in pse_and_ppse_dgi: if dgi_name == 'Store_PSE_1': dgi = process_pse_and_ppse(fh, dgi_name, True) else: dgi = process_pse_and_ppse(fh, dgi_name, False) cps.add_dgi(dgi) continue dgi_mark = fh.read_binary(fh.current_offset, 1) #DGI标识 if dgi_mark != '86': return next_len = get_next_len(fh) dgi_seq = fh.read_binary(fh.current_offset, 2) #读取DGI序号 dgi.name = dgi_seq next_len = get_next_len(fh) n_dgi_seq = utils.hex_str_to_int(dgi_seq) if n_dgi_seq <= 0x0B00: #认为是记录 template70 = fh.read_binary(fh.current_offset, 1) if template70 != '70': return next_len = get_next_len(fh) dgi_data = fh.read_binary(fh.current_offset, next_len) if n_dgi_seq <= 0x0B00 or (dgi_seq not in do_not_parse_tlv_list 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) dgi.add_tag_value(dgi_seq, 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_seq, dgi_data) cps.add_dgi(dgi) if rule_file is not None: process_rule(rule_file, cps) process_rule_A001(rule_file, cps) process_rule_eps(rule_file, cps) cps_list.append(cps) return cps_list
def process_dp(dp_file, rule_file): cps_list = [] fh = FileHandle(dp_file, 'rb+') dp_flag = fh.read_binary(fh.current_offset, 7) data_len = utils.hex_str_to_int(fh.read_binary(fh.current_offset, 8)) dgi_count = fh.read_int64(fh.current_offset) dgi_list = [] for i in range(dgi_count): dgi_name_len = fh.read_int(fh.current_offset) dgi_name = fh.read_str(fh.current_offset, dgi_name_len) dgi_list.append(dgi_name) card_seq = fh.read_binary(fh.current_offset, 4) card_data_len = fh.read_int(fh.current_offset) while data_len > fh.current_offset: cps = Cps() cps.dp_file_path = dp_file for item in dgi_list: dgi = Dgi() start_flag = fh.read_binary(fh.current_offset, 1) if start_flag != '86': return cps_list dgi_len = get_len(fh) dgi_name = fh.read_binary(fh.current_offset, 2) dgi.name = dgi_name dgi_data_len = utils.hex_str_to_int( fh.read_binary(fh.current_offset, 1)) n_dgi_seq = utils.hex_str_to_int(dgi_name) if n_dgi_seq <= 0x0B00: #认为是记录 template70 = fh.read_binary(fh.current_offset, 1) if template70 != '70': return cps_list dgi_data_len = get_len(fh) dgi_data = fh.read_binary(fh.current_offset, dgi_data_len) if item[0:3] == 'PSE': dgi = process_pse_and_ppse(dgi_name, dgi_data, 'PSE') elif item[0:4] == 'PPSE': dgi = process_pse_and_ppse(dgi_name, dgi_data, 'PPSE') else: if n_dgi_seq <= 0x0B00 or (utils.is_rsa(dgi_name) 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) 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, dgi_data) cps.add_dgi(dgi) if rule_file is not None: process_rule(rule_file, cps) cps_list.append(cps) return cps_list
def process_pse(dgi,data): pse_dgi = Dgi() if dgi == '0098': pse_dgi.name = '0101' pse_dgi.add_tag_value(pse_dgi.name,data[4:]) elif dgi == '0099': pse_dgi.name = '9102' pse_dgi.add_tag_value(pse_dgi.name,data) return pse_dgi
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
def process_merge_tag(self, src_dgi, src_tag, dst_dgi, dst_tag): dst_item = self.cps.get_dgi(dst_dgi) dst_tag_value = dst_item.get_value(dst_tag) src_item = self.cps.get_dgi(src_dgi) if src_item is None: dgi = Dgi() dgi.name = src_dgi dgi.add_tag_value(src_tag, dst_tag_value) self.cps.add_dgi(dgi) return self.cps else: for item in self.cps.dgi_list: if item.name == src_dgi: value = item.get_value(src_tag) value += dst_tag_value item.modify_value(src_tag, value) return self.cps return self.cps
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
def process_add_kcv(self, src_dgi, dst_dgi, key_type): item = self.cps.get_dgi(dst_dgi) key = item.get_value(item.name) key_len = len(key) kcv = '' if key_type == 'DES': for i in range(0, key_len, 32): part_key = key[i:i + 32] kcv += algorithm.des3_ecb_encrypt(part_key, '0000000000000000')[0:6] elif key_type == 'SM': for i in range(0, key_len, 32): part_key = key[i:i + 32] kcv += algorithm.sm4_ecb_encrypt( part_key, '00000000000000000000000000000000')[0:6] dgi = Dgi() dgi.name = src_dgi dgi.add_tag_value(dgi.name, kcv) self.cps.add_dgi(dgi) return self.cps
def process_pse_and_ppse(dgi_name, dgi_data, dgi_node): dgi = Dgi() dgi.name = dgi_node if dgi_name == '9102': index = dgi_data.find('A5') dgi_data = dgi_data[index:len(dgi_data)] dgi.add_tag_value(dgi_name, dgi_data) else: dgi.add_tag_value(dgi_name, dgi_data) return dgi
def process_assemble_dgi(self, src_dgi, src_tag, format_str): data = "" tag_list = format_str.split(',') for tag in tag_list[::-1]: if '.' not in tag: #说明是模板 data = tag + utils.get_strlen(data) + data else: dst_dgi = tag.split('.')[0] dst_tag = tag.split('.')[1] if dst_dgi == '': data = dst_tag + data elif dst_dgi[len(dst_dgi) - 1] == 'v': dst_dgi = dst_dgi[0:len(dst_dgi) - 1] value = self.cps.get_tag_value(dst_dgi, dst_tag) if not value: print('dgi %s tag %s 不存在' % (dst_dgi, dst_tag)) data = value + data else: value = '' if dst_dgi in ('9102', '9103'): #对于9103,9102需要特殊处理 tlvs = utils.parse_tlv( self.cps.get_tag_value(dst_dgi, dst_dgi)) for tlv in tlvs: if tlv.tag == dst_tag: value = tlv.value break else: value = self.cps.get_tag_value(dst_dgi, dst_tag) if not value: print('dgi %s tag %s 不存在' % (dst_dgi, dst_tag)) tag_len = utils.get_strlen(value) data = dst_tag + tag_len + value + data dgi = Dgi() dgi.name = src_dgi dgi.add_tag_value(src_tag, data) self.cps.add_dgi(dgi) return self.cps
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
def parse_9000(xml, goldpac_dgi_list, is_second_app): sddf_9000_ac = get_sddf_tag(xml, 'EMVDataName', 'Checksum Kac') sddf_9000_mac = get_sddf_tag(xml, 'EMVDataName', 'Checksum Ksmi') sddf_9000_enc = get_sddf_tag(xml, 'EMVDataName', 'Checksum Ksmc') dgi = Dgi() if is_second_app: dgi.name = '9000_2' else: dgi.name = '9000' data = get_goldpac_data(goldpac_dgi_list, sddf_9000_ac, is_second_app)[0:6] data += get_goldpac_data(goldpac_dgi_list, sddf_9000_mac, is_second_app)[0:6] data += get_goldpac_data(goldpac_dgi_list, sddf_9000_enc, is_second_app)[0:6] dgi.add_tag_value(dgi.name, data) return dgi
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
def parse_8000(xml, goldpac_dgi_list, is_second_app): sddf_8000_ac = get_sddf_tag(xml, 'EMVDataName', 'Kac') sddf_8000_mac = get_sddf_tag(xml, 'EMVDataName', 'Ksmi') sddf_8000_enc = get_sddf_tag(xml, 'EMVDataName', 'Ksmc') dgi = Dgi() if is_second_app: dgi.name = '8000_2' else: dgi.name = '8000' data = get_goldpac_data(goldpac_dgi_list, sddf_8000_ac, is_second_app) data += get_goldpac_data(goldpac_dgi_list, sddf_8000_mac, is_second_app) data += get_goldpac_data(goldpac_dgi_list, sddf_8000_enc, is_second_app) rule_file_handle = RuleXml(xml.file_name) _, key = rule_file_handle.get_decrypted_attribute('8000') #顺带解密 data = algorithm.des3_ecb_decrypt(key, data) dgi.add_tag_value(dgi.name, data) return dgi
def process_EF02(cps): data_ef02 = '' for item in cps.dgi_list: if item.name == '01': data_ef02 = item.get_value('EF02') data_ef02 = data_ef02[8:] #EF02总长度 for i in range(8): bcd_item_len = data_ef02[0 : 8] n_item_len = int(utils.bcd_to_str(bcd_item_len)) * 2 value = data_ef02[8 : 8 + n_item_len] data_ef02 = data_ef02[8 + n_item_len :] dgi = Dgi() if i == 3: dgi.name = '8205' dgi.add_tag_value(dgi.name,value) cps.add_dgi(dgi) elif i == 4: dgi.name = '8204' dgi.add_tag_value(dgi.name,value) cps.add_dgi(dgi) elif i == 5: dgi.name = '8203' dgi.add_tag_value(dgi.name,value) cps.add_dgi(dgi) elif i == 6: dgi.name = '8202' dgi.add_tag_value(dgi.name,value) cps.add_dgi(dgi) elif i == 7: dgi.name = '8201' dgi.add_tag_value(dgi.name,value) cps.add_dgi(dgi) return cps
def process_ppse(dgi,data): ppse_dgi = Dgi() if dgi == '0100': ppse_dgi.name = '9102' ppse_dgi.add_tag_value(ppse_dgi.name,data) return ppse_dgi
def parse_sddf_data(xml, sddf_tag, goldpac_dgi_list=[]): sddf_data = '' for item in goldpac_dgi_list: if item.goldpac_dgi == sddf_tag: sddf_data = item.data dgi = Dgi() node_dgi, value_format = get_tag_link_attribute(xml, sddf_tag) if node_dgi == '' or value_format == '': return None need_remove_template = is_need_delete_template(node_dgi) global _aid_list_info is_second_app = False for _, aid_info in _aid_list_info.items(): if sddf_tag[4] == aid_info[0]: is_second_app = aid_info[1] break if is_second_app: #说明包含双应用 dgi.name = node_dgi + '_2' else: dgi.name = node_dgi if value_format == 'TLV': data = utils.remove_dgi(sddf_data, node_dgi) if need_remove_template: data = utils.remove_template70(data) if utils.str_to_int(node_dgi) > 0xA000 or not utils.is_tlv(data): dgi.add_tag_value(dgi.name, data) else: 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: if tlv.len > 0x7F: value = tlv.tag + '81' + utils.int_to_hex_str( tlv.len) + tlv.value else: value = tlv.tag + utils.int_to_hex_str( tlv.len) + tlv.value dgi.add_tag_value(tlv.tag, value) elif value_format == 'V': dgi.add_tag_value(dgi.name, sddf_data) return dgi
def process_dp(dp_file, rule_file, is_mc_app=False): global _is_mc_app _is_mc_app = is_mc_app cps_list = [] fh = FileHandle(dp_file, 'rb+') dp_header = fh.read_binary(fh.current_offset, 26) dgi_count = fh.read_int(fh.current_offset) goldpac_dgi_list = [] for i in range(dgi_count): #获取sddf dgi个数及所包含数据的长度 item = GoldpacDgi() item.goldpac_dgi = fh.read_binary(fh.current_offset, 4) item.data_len = fh.read_int(fh.current_offset) goldpac_dgi_list.append(item) for item in goldpac_dgi_list: #获取sddf dgi所包含的数据 item.data = fh.read_binary(fh.current_offset, item.data_len) Log.info(item.goldpac_dgi + ' = ' + item.data) xml = XmlParser(rule_file) get_aid_list_info(xml) #获取AID应用列表信息 sddf_dgi_list = [] sddf_element_nodes = xml.get_nodes(xml.root_element, 'SDDFElement') constans_second_app = has_second_app() for node in sddf_element_nodes: sddf_tag = xml.get_attribute(node, 'SDDFTag') sddf_value = xml.get_attribute(node, 'Value') sddf_elements = parse_sddf_element(sddf_tag, sddf_value) sddf_dgi_list.extend(sddf_elements) cps = Cps() cps.dp_file_path = dp_file pse_dgi_list, ppse_dgi_list = get_pse_and_ppse_dgi_list(sddf_dgi_list) for sddf_tag in sddf_dgi_list: if sddf_tag not in pse_dgi_list and sddf_tag not in ppse_dgi_list: #解析TagLink节点,并生成cps数据 cps_dgi = parse_sddf_data(xml, sddf_tag, goldpac_dgi_list) if cps_dgi != None: cps.add_dgi(cps_dgi) dgi_8000 = parse_8000(xml, goldpac_dgi_list, False) dgi_9000 = parse_9000(xml, goldpac_dgi_list, False) cps.add_dgi(dgi_8000) cps.add_dgi(dgi_9000) if is_mc_app: dgi_A006 = parse_A006(xml, goldpac_dgi_list) cps.add_dgi(dgi_A006) dgi_A016 = Dgi() dgi_A016.name = 'A016' dgi_A016.add_tag_value('A016', dgi_A006.get_value('A006')) dgi_8001 = Dgi() dgi_8001.name = '8001' dgi_8001.add_tag_value('8001', dgi_8000.get_value('8000')) dgi_9001 = Dgi() dgi_9001.name = '9001' dgi_9001.add_tag_value('9001', dgi_9000.get_value('9000')) cps.add_dgi(dgi_8001) cps.add_dgi(dgi_9001) cps.add_dgi(dgi_A016) rsa_dgi_list = split_rsa(xml, goldpac_dgi_list, False) for rsa_dgi in rsa_dgi_list: cps.add_dgi(rsa_dgi) pse_dgi, ppse_dgi = parse_pse_and_ppse(xml, pse_dgi_list, ppse_dgi_list, goldpac_dgi_list) if pse_dgi.is_empty() is False: cps.add_dgi(pse_dgi) if ppse_dgi.is_empty() is False: cps.add_dgi(ppse_dgi) if constans_second_app: cps = process_jetco_special_dgi(xml, goldpac_dgi_list, cps) cps.add_dgi(parse_8000(xml, goldpac_dgi_list, True)) cps.add_dgi(parse_9000(xml, goldpac_dgi_list, True)) rsa_dgi_list = split_rsa(xml, goldpac_dgi_list, True) for rsa_dgi in rsa_dgi_list: cps.add_dgi(rsa_dgi) cps_list.append(cps) return cps_list
def parse_store_data(self, app_type, dgi_name, data, session_key=None, is_encrypted=False, delete80_list=[]): int_dgi_name = int(dgi_name, 16) if is_encrypted and session_key: data = des3_ecb_decrypt(session_key, data) if dgi_name in delete80_list: index = data.rfind('80') if index != -1: data = data[0:index] #对于PSE和PPSE,不解析TLV格式 if app_type in ('PSE', 'PPSE'): dgi = Dgi() dgi.name = app_type if data.startswith('70'): data = data[4:] #去掉70模板 dgi.add_tag_value(dgi_name, data) return dgi else: #规则如下: #1. 小于0x0B00的记录数据需要解析TLV结构 #2. 如果DGI大于0B00,并且该数据可以解析成TLV,则分如下情况 # a. 如果是8000,9000,9102,9103等不需要分析TLV结构的,则不分析 # b. 如果DGI以A,B字母开头(万事达应用),不用做TLV分析 if int_dgi_name <= 0x0B00 \ or (dgi_name not in self.do_not_parse_tlv_list \ and utils.is_tlv(data)\ and not (dgi_name.startswith('A') or dgi_name.startswith('B')) ): if utils.is_tlv(data): tlvs = utils.parse_tlv(data) return self._assemble_dgi(dgi_name, tlvs) else: dgi = Dgi() dgi.name = dgi_name dgi.add_tag_value(dgi_name, data) return dgi else: dgi = Dgi() dgi.name = dgi_name if dgi_name.endswith('_2'): dgi_name = dgi_name[:-2] dgi.add_tag_value(dgi_name, data) return dgi
def _process_pse_and_ppse(dgi_name, data): dgi = Dgi() if dgi_name == 'Store_PSE_1': dgi.name = 'PSE' data = utils.remove_dgi(data, '0101') data = utils.remove_template70(data) dgi.add_tag_value('0101', data) elif dgi_name == 'Store_PSE_2': dgi.name = 'PSE' data = utils.remove_dgi(data, '9102') value = utils.assemble_tlv('A5', '880101' + data) dgi.add_tag_value('9102', value) elif dgi_name == 'Store_PPSE': dgi.name = 'PPSE' # value = dgi.assemble_tlv('BF0C',data) # value = dgi.assemble_tlv('A5',value) data = utils.remove_dgi(data, '9102') dgi.add_tag_value('9102', data) return dgi
def process_data(app_flag, card_data): dgi = Dgi() dgi.name = app_flag data = card_data.split('|') dgi.add_tag_value(data[0], data[2]) return dgi
def process_pse_and_ppse(fh, dgi_name, has_template): dgi = Dgi() data = '' dgi_mark = fh.read_binary(fh.current_offset, 1) #DGI标识 if dgi_mark != '86': return next_len = get_next_len(fh) if has_template: fh.read_binary(fh.current_offset, 1) #读取70模板 next_len = get_next_len(fh) data = fh.read_binary(fh.current_offset, next_len) else: data = fh.read_binary(fh.current_offset, next_len) if dgi_name == 'Store_PSE_1': dgi.name = 'PSE' #value = dgi.assemble_tlv('0101',data) dgi.add_tag_value('0101', data) elif dgi_name == 'Store_PSE_2': dgi.name = 'PSE' value = utils.assemble_tlv('A5', '880101' + data) dgi.add_tag_value('9102', value) elif dgi_name == 'Store_PPSE': dgi.name = 'PPSE' value = utils.assemble_tlv('BF0C', data) value = utils.assemble_tlv('A5', value) dgi.add_tag_value('9102', value) else: dgi.name = 'F001' dgi.add_tag_value('F001', data) return dgi