Skip to main content

2 posts tagged with "nfc"

View All Tags

Ce înseamnă să integrezi CEI prin NFC. Un ghid pentru ingineri.

· 8 min read
Cătălin Toma
Founder, EidKit

Acesta este al treilea articol din seria noastră despre carta electronică de identitate. Articolele anterioare acoperă problema adresei care strică fluxurile KYC și ce poate semna buletinul tău electronic.

Dacă ai mai integrat un pașaport electronic sau un alt document de identitate cu cip, vei intra în acest proiect cu un set de presupuneri rezonabile. Cele mai multe dintre ele sunt parțial greșite pentru CEI.

Nu este că standardele ICAO nu se aplică — se aplică, ca punct de plecare. Problema este că CEI este un card de identitate național cu extensii specifice care nu apar nicăieri documentate complet în public. Ce urmează este o hartă a terenului bazată pe implementări complete pentru Android și iOS, testate pe carduri CEI reale.


Ce știi deja — și ce se aplică

Orice card de identitate electronic bazat pe standardele ICAO folosește PACE (Password Authenticated Connection Establishment) pentru a stabili un canal securizat înainte de a permite citirea oricărui datum. CEI face același lucru, cu codul CAN — 6 cifre tipărite pe fața cardului — ca parolă.

Rezultatul PACE este un canal Secure Messaging (SM) care împachetează toate comenzile APDU ulterioare. Orice comandă trimisă raw după stabilirea canalului este respinsă de card — comportament standard, nu specific CEI.

Autentificarea pasivă funcționează după principii cunoscute pe ambele platforme: cipul conține un Security Object Document care înlănțuie hash-urile SHA-256 ale grupelor de date până la certificatul rădăcină CSCA al MAI. Verificarea arată diferit în funcție de platformă, dar principiul este același:

Pe Android, jMRTD gestionează parsarea SOD-ului. Verificarea lanțului se face manual față de certificatul CSCA distribuit în bundle cu SDK-ul:

val sod = SODFile(sodRaw.inputStream())
val dsc = sod.docSigningCertificate
val csca = assets.open("csca_romania.der").use {
CertificateFactory.getInstance("X.509").generateCertificate(it) as X509Certificate
}
dsc.verify(csca.publicKey) // aruncă excepție dacă invalid

Autentificarea pasivă trebuie să ruleze întotdeauna înainte de a folosi datele citite. Până aici, un inginer cu experiență în documente ICAO va fi confortabil. Aceasta este și cam limita terenului familiar.


Unde presupunerile încep să se destrame

Cipul are patru applet-uri, nu unul

Documentele de călătorie ICAO standard au o structură de applet relativ predictibilă. CEI nu urmează același tipar. Cipul conține patru applet-uri cu roluri distincte:

AppletRol
AID1 / National AppPunct de intrare PACE, găzduiește parametrii de securitate
ICAO LDSFotografie, semnătură olografă digitizată, SOD pentru autentificare pasivă
EDATADate personale: nume, CNP, adresă de domiciliu
GenPKIChei și certificate pentru autentificare activă și semnare

Applet-ul ESIGN există pe cip și apare în unele documente de referință. Nu este folosit. Semnarea se face prin GenPKI, printr-o comandă diferită de ce ai presupune din lectura standardelor.

Fiecare applet urmează propriul flux de selecție și autentificare. Nu selectezi un applet și citești ce ai nevoie.

Două faze, cerințe diferite

Citirea datelor de pe CEI se împarte natural în două faze:

Faza 1 — doar CAN: accesează datele disponibile fără PIN — fotografia titularului, semnătura olografă digitizată și datele necesare pentru autentificarea pasivă. Această fază folosește applet-ul ICAO standard.

Faza 2 — CAN + PIN de 4 cifre: accesează datele personale complete din applet-ul EDATA, inclusiv adresa de domiciliu — care nu mai apare tipărită pe cardul fizic.

Ordinea operațiilor înainte de PACE nu este documentată — și contează

Ce trebuie să faci înainte de PACE depinde de ce vrei să faci după PACE, iar regulile sunt asimetrice în funcție de scenariu. Faza 1 cere o pregătire diferită față de Faza 2 și GenPKI. Dacă pregătirea nu este cea corectă, eșuările apar în puncte neașteptate cu coduri de eroare care nu indică problema reală.

Situația este diferită pe cele două platforme din motive arhitecturale:

Stack-ul NFC Android pornește în contextul MF — niciun AID nu este pre-selectat. Aceasta este starea corectă pentru Faza 1: PACE funcționează direct în context MF, după care SM SELECT ICAO oferă acces la DG2/DG7/SOD.

// Faza 1: nicio pre-selecție necesară — stack-ul Android pornește în MF
isoDep.timeout = 20_000 // timeout-ul implicit este insuficient pentru CEI

val paceResult = ps.doPACE(canKey, paceOid, paceParams, null)
val wrapper = paceResult.wrapper
// toate comenzile de acum înainte trec prin wrapper

// Faza 2: SELECT AID1 înainte de PACE — chip-ul cere context AID1 pentru EDATA/GenPKI

Comportamentul asimetric al pregătirii pre-PACE nu este documentat nicăieri — a fost descoperit prin eliminare pe ambele platforme.


Formatele de date: unde implementarea românească diverge

DG1 nu este MRZ

Acesta este momentul în care codul care funcționează perfect la pașapoarte se rupe complet, pe ambele platforme. Datele de identitate returnate de applet-ul EDATA nu sunt în formatul MRZ pe care îl parsează bibliotecile ICAO standard — sunt într-un format ASN.1 specific implementării românești, cu diacritice corecte și câmpuri structurate diferit:

SEQUENCE (0x30)
[0] (0x80) lastName UTF-8 ex. "TOMA"
[1] (0x81) firstName UTF-8 ex. "CĂTĂLIN" (cu diacritice)
[2] (0x82) sex UTF-8 "M" sau "F"
[3] (0x83) dateOfBirth UTF-8 DDMMYYYY
[4] (0x84) cnp UTF-8 13 cifre
[5] (0x85) nationality UTF-8 "ROU"

jMRTD's DG1File nu poate parsa acest format. Este nevoie de un parser propriu:

// jMRTD nu ajută aici — format ASN.1 specific românesc
val tags = parseContextTags(dg1Bytes) // parser propriu
val lastName = tags[0x80]?.toString(Charsets.UTF_8)
val firstName = tags[0x81]?.toString(Charsets.UTF_8) // diacriticele sunt corecte
val cnp = tags[0x84]?.toString(Charsets.UTF_8)

Formatul nu este documentat public — a fost determinat prin inspecție directă a bytes returnați de card.

Cele două chei criptografice din GenPKI

GenPKI conține două chei distincte, pe curbe eliptice diferite, cu comportamente interne diferite la semnare:

OperațiunePINComportament intern
Autentificare activă4 cifreCheie pe secp384r1, referință 0x81
Semnare document6 cifreCheie pe brainpoolP384r1, referință 0x8E

A le confunda produce semnături incorecte fără niciun mesaj de eroare care să indice cauza. Comportamentul este identic pe Android și iOS — aceasta este o constrângere a cipului, nu a platformei.


Lucruri care se rup înainte să ajungi la logica de business

Furnizorul criptografic trebuie înregistrat explicit, în ordinea corectă, înainte de orice operație pe cip. Ordinea greșită produce eșuări silențioase:

Security.removeProvider("BC")
Security.insertProviderAt(BouncyCastleProvider(), 1)

Android 13+ a schimbat API-ul pentru interceptarea tag-urilor NFC. Dacă suporți versiuni mai vechi, gestionezi două variante cu comportamente ușor diferite.

PIN counter query nu funcționează în modul SM, pe nicio platformă. Nu există cale să interoghezi numărul de încercări rămase înainte de a trimite PIN-ul efectiv. Tratezi SW=63CX în răspunsul la VERIFY (X = încercări rămase) și SW=6983 pentru card blocat — detaliu care afectează direct UX-ul aplicației.


Scriem despre CEI — capabilitățile sale, provocările de integrare și contextul reglementar din jurul său. Dacă un subiect de aici este relevant pentru ce construiești, scrie-ne.

Adresa ta e pe buletin. Banca nu știe cum să o citească.

· 7 min read
Cătălin Toma
Founder, EidKit

Acesta este primul articol din seria noastră despre carta electronică de identitate. Al doilea acoperă ce poate semna buletinul tău și ce nu poate semna încă.

Odată cu introducerea noii Cărții Electronice de Identitate, adresa de domiciliu a dispărut de pe suprafața fizică a documentului. Nu mai există stradă, număr, oraș, județ tipărite pe verso. Toate aceste informații sunt stocate exclusiv pe cipul din interiorul cărții, accesibile doar prin NFC sau printr-un cititor de carduri.

În teorie, este un pas înainte. Adresa poate fi actualizată electronic atunci când te muți, fără să fie necesară emiterea unui nou document. În practică, tranziția a generat o criză care devine tot mai vizibilă.


Problema, pe scurt

Milioane de români dețin acum un act de identitate care conține legal adresa lor de domiciliu — dar nu o pot prezenta unui funcționar bancar, notar sau angajat al statului într-un format pe care acesta să îl poată citi.

Până în această săptămână, Guvernul a înregistrat peste 300 de sesizări în categoria „Pașaport și Carte de Identitate" pe platforma fara-hartie.gov.ro. Cea mai frecventă problemă: lipsa adresei tipărite. Bănci, notariate, școli, birouri ANAF și autorități locale continuă să solicite o adeverință de domiciliu separată — un document care atestă adresa deja prezentă, tehnic vorbind, pe actul pe care îl țin în mână.

O persoană a povestit că a ajuns la notar pentru un act de vânzare-cumpărare și a fost trimisă acasă pentru că CEI „nu este suficientă pentru dovada domiciliului." Alta a pățit același lucru la bancă. Un tânăr de 34 de ani: „Am făcut buletinul electronic pentru că am înțeles că e mai modern și mai sigur. Nimeni nu mi-a spus că voi avea nevoie de o adeverință de fiecare dată când trebuie să dovedesc adresa."

Asta se întâmplă când infrastructura avansează înainte ca instituțiile să fie pregătite să o folosească.


Ce a făcut Guvernul

Guvernul a reacționat rapid. Pe 25 martie 2026 — acum două zile — serviciile de evidență a persoanelor au primit instrucțiunea să verifice ele însele adresele în baza de date națională, fără să mai condiționeze preluarea dosarului de prezentarea unui document fizic.

Băncile au primit acces tehnic direct la baza de date a evidenței persoanelor și, conform anunțului guvernamental, nu mai trebuie să solicite adeverința.

Pentru notari, se testează un mecanism similar.

Pentru toți ceilalți — cetățeni care trebuie să dovedească adresa într-un loc care nu are încă acces la baza de date — Ministerul Afacerilor Interne a lansat aplicația mobilă RoCEIReader. Apropiați buletinul de telefon, introduceți codul CAN de 6 cifre și PIN-ul de 4 cifre, iar aplicația citește adresa de pe cip și permite salvarea ei ca PDF.

Disponibilă momentan doar pentru Android. Versiunea iOS „urmează în curând."

Forma acestei soluții

Răspunsul Guvernului la „instituțiile nu pot citi cipul" este o aplicație pentru cetățeni, prin care aceștia citesc cipul ei înșiși și produc un PDF. Acel PDF este apoi prezentat instituției care nu putea citi cipul.

Problema a fost parțial convertită dintr-o provocare de integrare tehnică în birocrație — birocrație digitală, dar tot birocrație. Funcționează și e mai bine decât nimic. Dar ilustrează bine distanța dintre ce este CEI — un card inteligent NFC cu securitate criptografică și date semnate de stat — și ce sunt pregătite majoritatea sistemelor să facă cu el.


Opțiunile pentru citirea adresei

Tranziția are consecințe reale pentru oricine construiește software care necesită o adresă de domiciliu verificată în România. Fluxul vechi — scanează actul, extrage adresa prin OCR de pe verso — nu mai funcționează. Adresa nu mai e pe verso.

Alternativele, aproximativ în ordinea robusteții:

Acces direct la baza de date guvernamentală Băncile au primit acces direct la registrul DGEP. Curat, fără NFC, fără interacțiune suplimentară din partea utilizatorului dincolo de CNP. Accesul necesită un acord formal cu autoritatea guvernamentală și nu este disponibil oricărei companii private care îl solicită.

Citirea cipului prin NFC Cardul este citit direct folosind codul CAN tipărit pe fața documentului. Adresa este furnizată exact așa cum o deține statul — semnată criptografic, verificabilă față de lanțul de certificate al Ministerului, fără dependență de o bază de date externă. Adresa se află în applet-ul EDATA al cardului, în spatele unui canal securizat PACE și al unui PIN de 4 cifre. Citirea corectă implică gestionarea unor formate de date specifice implementării românești, pe care bibliotecile ICAO standard nu le acoperă din cutie.

Certificatul produs de utilizator Soluția de compromis facilitată acum prin RoCEIReader. Valabilă legal. Introduce un pas manual pentru utilizator, o fereastră de valabilitate de 6 luni și fricțiune tocmai acolo unde fluxurile de onboarding pierd cei mai mulți utilizatori.


Imaginea de ansamblu

Problema adresei este simptomul cel mai vizibil, dar CEI este capabilă de mult mai mult decât a reușit să asimileze orice instituție până acum.

Cipul conține date biometrice, fotografia titularului și două chei criptografice susținute de certificate emise de MAI. Una este pentru semnătura electronică avansată — conform Legii 214/2024, un document semnat cu acest certificat are aceeași valoare juridică ca o semnătură olografă. Cealaltă este pentru autentificarea activă: o dovadă criptografică că cipul este autentic și nu clonat.

Și totuși, platforma SPV a ANAF respinge semnătura de pe CEI. Acceptă doar semnături de pe certificate calificate achiziționate separat, de la furnizori comerciali autorizați. Cardul îți oferă o semnătură legal valabilă. Portalul propriu al Guvernului nu o acceptă.

Cardul este înaintea ecosistemului. Ecosistemul recuperează decalajul, instituție cu instituție. Băncile au recuperat în privința adresei. Notarii sunt aproape. ANAF nu a recuperat în privința semnăturilor. Același tipar se va repeta pentru fiecare instituție care trebuie să interacționeze cu aceste carduri în următorii doi-trei ani.


Ce presupune citirea cipului

Pentru cei curioși din punct de vedere tehnic: cipul CEI rulează protocolul PACE (Password Authenticated Connection Establishment) cu AES-256 pentru a stabili un canal securizat înainte ca orice să poată fi citit. După deschiderea canalului, citirea datelor personale necesită selectarea applet-ului corect, verificarea PIN-ului și parsarea răspunsului într-un format ASN.1 specific implementării românești — diferit de formatul MRZ ICAO pe care îl așteaptă majoritatea bibliotecilor.

Autentificarea pasivă — verificarea că datele de pe cip sunt semnate de MAI și nu au fost alterate — trebuie să ruleze întotdeauna înainte de a folosi orice date citite de pe card. Lanțul merge de la grupele de date prin certificatul semnatarului documentului până la certificatul rădăcină CSCA al Ministerului.

Nimic din toate astea nu este exotic. Dar este specific, iar specificul contează. Nu poți integra CEI citind documentația ICAO standard și adaptând un cititor de pașapoarte. Implementarea românească are propria structură de applet-uri, propriile formate de date și propriile cerințe de secvențiere care nu sunt documentate complet nicăieri în mod public.


Din iulie 2025, CEI este singurul model de carte de identitate emis la nivel național. Fiecare act de identitate eliberat în România de acum înainte conține un cip pe care titularul nu îl poate prezenta majorității instituțiilor într-un format pe care acestea să îl poată citi.

Decalajul se va închide treptat. Întrebarea pentru oricine construiește în acest spațiu este cât timp este dispus să aștepte și dacă soluția de compromis — certificate PDF ale datelor deja existente pe card — reprezintă fricțiunea acceptabilă pentru produsul său.


Scriem despre CEI — capabilitățile sale, provocările de integrare și contextul reglementar din jurul său. Dacă un subiect de aici este relevant pentru ce construiești, scrie-ne.