Ma per farci cosa?
leggere dati anagrafici, tipo nome, cognome, data e luogo di nascita ... altro?! boh, per ora dovrebbe essere sufficiente
(mi riferisco alle Tessere Sanitarie ma se possibile anche altro ... Carta d'identità?)
EDIT: io prima di iniziare pensavo ci fosse in dotazione un software per leggere e con cui dialogare, un pò come mi è capitato per altri device, invece ci sono solo driver
Ultima modifica di muttley005; 06-06-2020 11:59
sono andato un pò avanti e per accorciare i tempi ho provato a sfruttare il software Cardpeek
questo sfrutta degli script LUA e ne ho trovato uno (Netlink) che, leggermente corretto (mi dava errori in fase di formattazione delle date), fa quel che deve e legge i dati a cui voglio arrivare.
Andando oltre ho visto che si può anche sfruttare (Cardpeek) da line-command per cui ora riesco facilmente da mio programma tramite un pulsante ad attivare la lettura da smartcard e a creare un XML contenente i dati richiesti.
La linea di comando che ho utilizzato è "Cardpeek -r "nome mio smart card reader" -e "dofile('netlink.lua'); ui.save_view('miopath\\card.xml');ui.exit()"
Ora ho un file CARD.XML che pensavo di leggere facilmente (l'ho già fatto altre volte) ma al LOAD da errore
card.zip (ridotto all'osso per nascondere i dati sensibili e per capire se l'errore fosse dovuto a qualcosa nella struttura) che riporto anche qui sotto:
<?xml version="1.0" type="UTF-8"?> <cardpeek> <version>0.8.4-win32</version> <node> <attr name="classname">card</attr> <attr name="label">Healthcare card (Netlink)</attr> <node> <attr name="classname">atr</attr> <attr name="label">cold ATR</attr> <attr name="size">24</attr> <attr name="val" encoding="bytes">8:3BDF18008131FE7D006B020C0182011101434E53103180FC</attr> </node> </node> </cardpeek>e questo il codice che uso normalmente
Function prova() Call Leggi_XML("Z:\@Matteo\Desktop", "card_mini.xml") End Function Public Function Leggi_XML(PercorsoXML As String, FileXML As String) As Byte Dim myXML As MSXML2.DOMDocument60 'Object 'DOMDocument Dim myNL As MSXML2.IXMLDOMNodeList 'Object 'IXMLDOMNodeList Dim myNode As MSXML2.IXMLDOMNode 'Object 'IXMLDOMNode Dim OK As Boolean 'accesso al file Set myXML = New MSXML2.DOMDocument60 myXML.async = False OK = myXML.Load(PercorsoXML & "\" & FileXML) If Not OK Then Leggi_XML = 0 GoTo FINE End If '... e poi il resto ma mi da errore sul LOAD end functionsono un pò ad un punto morto... qualche aiuto?
grazie
l'errore sul LOAD deriva dal fatto che il file XML esce con questa prima riga
<?xml version="1.0" type="UTF-8"?>se la sostituisco così
<?xml version="1.0" encoding="UTF-8"?>funziona ... peccato che nella documentazione viene specificato che dalla v.0.8.3 doveva già essere così e io ho la 0.8.4
dovrò leggerlo prima come file di testo, fare la sostituzione e poi caricarlo come XML
Suggerimenti per altre strade?
Alla fine ho fatto come preannunciato al post precedente sfruttando sw esterno che produce un XML che ricodifico e leggo.
Poi ho trovato un codice che sfrutta la libreria WinSCard.dll e l'ho adattato alle mie esigenze e tutto funziona egregiamente anche senza appoggiarmi a sw esterni.
In pratica mando codici al lettore che legge determinate "posizioni" e mi ritorna valori.
In questo modo ottengo una stringa unica relativa al "ramo" dati personali che poi "interpreto".
la parte di codice interessata è questa
'--------------------------------------------------------------------------- ' LIVELLO EF 1102 - DATI PERSONALI CONTENUTI NELLA CARTA '--------------------------------------------------------------------------- APDU(0) = &H0 'CLA APDU(1) = &HA4 'INS APDU(2) = &H9 'P1 APDU(3) = &H0 'P2 APDU(4) = &H2 'LC APDU(5) = &H11 APDU(6) = &H2 RecVLen = 257 ioSendReq.dwProtocol = ActiveProtocol ioSendReq.dwPciLength = Len(ioSendReq) ioRecVReq.dwProtocol = ActiveProtocol ioRecVReq.dwPciLength = Len(ioSendReq) RetVal = SCardTransmit(hCard, ioSendReq, APDU(0), 7, ioRecVReq, RecVBuff(0), RecVLen) If (RetVal <> 0) Then MsgBox ("Errore n." & CStr(RetVal)) Exit Function End If ' LEGGO I BINARY PROVENIENTI DALLA CARTA APDU(0) = &H0 'CLA APDU(1) = &HB0 'INS APDU(2) = &H0 'P1 APDU(3) = &H0 'P2 APDU(4) = &H9F 'LC RecVLen = 257 ioSendReq.dwProtocol = ActiveProtocol ioSendReq.dwPciLength = Len(ioSendReq) ioRecVReq.dwProtocol = ActiveProtocol ioRecVReq.dwPciLength = Len(ioSendReq) RetVal = SCardTransmit(hCard, ioSendReq, APDU(0), 5, ioRecVReq, RecVBuff(0), 400) If (RetVal <> 0) Then MsgBox ("Errore n." & CStr(RetVal)) GoTo CLOSE_CONNECTION End If DatiPersonali = vbNullString For i = 0 To 400 - 1 DatiPersonali = DatiPersonali + Chr(RecVBuff(i)) Next iora vorrei reperire il numero della smartcard quindi ho preso questo codice che è nel tscns.lua che avevo sfruttato per cardpeek
CRoot=card.tree_startup("Tessera Sanitaria / Carta Nazionale dei Servizi") DF0 = nodes.append(CRoot, {classname="record",label="DF0",val=nil}) DF1 = nodes.append(CRoot, {classname="record",label="DF1",val=nil}) DF2 = nodes.append(CRoot, {classname="record",label="DF2",val=nil}) card.send(bytes.new(8, "00 A4 00 00 02 3F 00")) card.send(bytes.new(8, "00 A4 00 00 02 10 00")) card.send(bytes.new(8, "00 A4 00 00 02 10 02")) sw, resp = card.read_binary('.') nodes.append(DF0, {classname="file",label="EF.Dati_processore",val=tostring(resp)}) card.send(bytes.new(8, "00 A4 00 00 02 10 03")) sw, resp = card.read_binary('.') nodes.append(DF0, {classname="file",label="EF.ID_Carta",val=tostring(resp)}) card.send(bytes.new(8, "00 A4 00 00 02 3F 00")) card.send(bytes.new(8, "00 A4 00 00 02 11 00")) card.send(bytes.new(8, "00 A4 00 00 02 11 01")) sw, resp = card.read_binary('.') nodes.append(DF1, {classname="file",label="EF.C_Carta",val=tostring(resp)}) card.send(bytes.new(8, "00 A4 00 00 02 11 02")) sw, resp = card.read_binary('.') nodes.append(DF1, {classname="file",label="EF_Dati_personali",val=tostring(resp)}) card.send(bytes.new(8, "00 A4 00 00 02 3F 00")) card.send(bytes.new(8, "00 A4 00 00 02 12 00")) card.send(bytes.new(8, "00 A4 00 00 02 12 01")) sw, resp = card.read_binary('.') nodes.append(DF2, {classname="file",label="EF.Dati_personali_aggiuntivi",val=tostring(resp)}) card.send(bytes.new(8, "00 A4 00 00 02 12 02")) sw, resp = card.read_binary('.') nodes.append(DF2, {classname="file",label="EF.Memoria_residua",val=tostring(resp)}) card.send(bytes.new(8, "00 A4 00 00 02 12 03")) sw, resp = card.read_binary('.') nodes.append(DF2, {classname="file",label="EF.Servizi installati",val=tostring(resp)}) card.disconnect()quindi pensavo che impostando questo (vedi corrispondenza di colori) avrei ottenuto il numero di SC ma così non è
APDU(0) = &H0 'CLA APDU(1) = &HA4 'INS APDU(2) = &H9 'P1 APDU(3) = &H0 'P2 APDU(4) = &H2 'LC APDU(5) = &H10 APDU(6) = &H3qualche aiuto?
Difficile risponderti ... sembra che ogni produttore di card utilizzi un proprio metodo.
Leggendo quello che scrivi comunque rilevo un'incongruenza sempre sul parametro P1 (tu usi &H9 mentre forse dovresti usare &H0).
Forse a questo link puoi trovare qualche spunto ...
si avevo notato anch'io questa incongruenza (è un pezzo di codice che ho trovato e utilizzato adattandolo)
Avevo già provato a cambiare entrambi da &H9 a &H0 ma ottengo gli stessi esiti.
proseguendo nella ricerca della soluzione ma anche comprensione sto facendo delle prove ahimè piuttosto casuali a sto punto perchè evidentemente mi sfugge la logica di funzionamento della lettura ...
finorà ho inviato questi codici, utilizzando l'array APDU in esadecimale ma scriverò la stringa per velocizzare:
1) [0 CA 0 81 0 0]
2) [0 A4 0 0 2 3F 0] 'Master File
3) [0 A4 0 0 2 11 0] 'Livello EF 1100 (Dati personali)
4) [0 A4 0 0 2 11 2] 'Livello EF 1102 (Dati personali dettaglio)
5) [0 B0 0 0 H9F] 'per leggere i binary
ottenendo poi i dati personali dal ciclo sull'array RECVBUF dopo la lettura dei binary
se aggiungo queste 3 righe dopo il punto 2)
3) [0 A4 0 0 2 10 0] ' ?
4) [0 A4 0 0 2 10 3] 'ID carta
5) [0 B0 0 0 H9F] 'per leggere i binary
ottengo finalmente l'id carta ma poi sembra non legga + dai rimanenti punti (ex 3,4,5 ora 6,7,8)
ma perchè?!
ok... se faccio 2 letture una con i punti 1,2,3,4,5 "prima versione" ottengo i dati personali poi chiudo la connessione e la riapro rieseguendo i punti 1 e 2 e poi i nuovi 3,4,5 ottengo tutto ma non è bello... anzi è veramente basso artigianato :S