1- from smartcard .System import readers
2- from smartcard .util import toHexString , toBytes
31import binascii
42import json
3+ import os
4+
5+ from smartcard .System import readers
6+ from smartcard .util import toHexString , toBytes
57
68def send_apdu (connection , apdu ):
79 data , sw1 , sw2 = connection .transmit (apdu )
@@ -12,15 +14,6 @@ def select_app(connection, aid_hex):
1214 apdu = [0x00 , 0xA4 , 0x04 , 0x00 , len (aid )] + aid + [0x00 ]
1315 return send_apdu (connection , apdu )
1416
15- def get_processing_options (connection , pdol = None ):
16- if pdol :
17- pdol_data = toBytes (pdol )
18- gpo_data = [0x83 , len (pdol_data )] + pdol_data
19- else :
20- gpo_data = [0x83 , 0x00 ]
21- apdu = [0x80 , 0xA8 , 0x00 , 0x00 , len (gpo_data )] + gpo_data + [0x00 ]
22- return send_apdu (connection , apdu )
23-
2417def read_record (connection , sfi , record ):
2518 apdu = [0x00 , 0xB2 , record , (sfi << 3 ) | 4 , 0x00 ]
2619 return send_apdu (connection , apdu )
@@ -96,7 +89,7 @@ def process_afl(connection, afl_data, script):
9689 print (f"Record { rec :02X} from SFI { sfi :02X} : { toHexString (resp )} " )
9790 return script
9891
99- def generate_arqc (connection , amount = "000000000100" , additional_data = "" ):
92+ def generate_arqc (connection , amount = "000000000100" ):
10093 # Standard EMV ARQC data format
10194 gen_ac_data = (
10295 "9F0206" + amount + # Amount
@@ -120,7 +113,7 @@ def get_processing_options(connection, pdol=None):
120113 resp , sw1 , sw2 = send_apdu (connection , apdu )
121114 if sw1 != 0x90 or sw2 != 0x00 :
122115 print (f"GPO failed: SW1={ sw1 :02X} , SW2={ sw2 :02X} " )
123- return resp , sw1 , sw2
116+ return resp , sw1 , sw2 , apdu
124117
125118def main ():
126119 r = readers ()
@@ -158,15 +151,10 @@ def main():
158151
159152 tlv = parse_tlv (resp )
160153 pdol = tlv .get ("9F38" , None )
161-
154+
162155
163156 # Step 3: GPO
164- resp , sw1 , sw2 = get_processing_options (connection , pdol )
165- gpo_apdu = [0x80 , 0xA8 , 0x00 , 0x00 ]
166- if pdol :
167- gpo_apdu += [len (toBytes (pdol )), 0x83 , len (toBytes (pdol ))] + toBytes (pdol ) + [0x00 ]
168- else :
169- gpo_apdu += [0x02 , 0x83 , 0x00 , 0x00 ]
157+ resp , sw1 , sw2 , gpo_apdu = get_processing_options (connection , pdol )
170158 script .append ({"apdu" : toHexString (gpo_apdu ).replace (" " , "" ).lower (),
171159 "response" : toHexString (resp ).replace (" " , "" )})
172160
@@ -184,18 +172,18 @@ def main():
184172 script = process_afl (connection , afl , script )
185173
186174 try :
187- # Generate ARQC
175+ # Generate ARQC
188176 resp , sw1 , sw2 = generate_arqc (connection )
189177 script .append ({
190178 "apdu" : toHexString ([0x80 , 0xAE , 0x80 , 0x00 ]).replace (" " , "" ).lower (),
191179 "response" : toHexString (resp ).replace (" " , "" )
192180 })
193- except :
194- pass
181+ except Exception as e :
182+ print (f"ARQC generation failed: { e } " )
183+ resp = []
195184 iad = parse_tlv (resp ).get ("9F10" , "" )
196185
197186 # Extract card data from records
198- app_name = None
199187 country_code = None
200188 cvm_list = None
201189 ctq_data = None
@@ -205,15 +193,15 @@ def main():
205193 record_tlv = parse_tlv (bytes .fromhex (record ['response' ]))
206194 if '70' in record_tlv :
207195 record_data = record_tlv ['70' ]
208-
196+
209197 # Country code (tag 5F28)
210198 if '5F28' in record_data :
211199 country_code = record_data ['5F28' ]
212-
200+
213201 # CVM List (tag 8E)
214202 if '8E' in record_data :
215203 cvm_list = record_data ['8E' ]
216-
204+
217205 # Card Transaction Qualifiers (tag 9F6C)
218206 if '9F6C' in record_data :
219207 ctq_data = record_data ['9F6C' ]
@@ -224,7 +212,6 @@ def main():
224212
225213
226214 # Create dumps directory if it doesn't exist
227- import os
228215 if not os .path .exists ('dumps' ):
229216 os .makedirs ('dumps' )
230217
@@ -239,9 +226,9 @@ def main():
239226 except Exception as e :
240227 print (f"Error parsing record: { e } " )
241228 continue
242-
229+
243230 output = {
244- "name" : f"{ app_label } _{ track2 [:6 ]} ] " ,
231+ "name" : f"{ app_label } _{ track2 [:6 ]} " ,
245232 "appName" : app_label ,
246233 "aid" : aid ,
247234 "pdol" : pdol .lower () if pdol else None ,
@@ -255,13 +242,13 @@ def main():
255242 # Generate filename
256243 filename = f"{ track2 or 'notrack2' } _{ aid } .json"
257244 filepath = os .path .join ('dumps' , filename )
258-
245+
259246 # Save to file
260247 with open (filepath , 'w' ) as f :
261248 f .write (json .dumps (output , indent = 4 , ensure_ascii = False ))
262-
249+
263250 print (f"Output saved to: { filepath } " )
264251 print (json .dumps (output , indent = 4 , ensure_ascii = False ))
265252
266253if __name__ == "__main__" :
267- main ()
254+ main ()
0 commit comments