Čitanje čipova pasoša iz React Nativea
Godine 2020. nijedna biblioteka to nije radila u stanju koje se moglo isporučiti. Šta je bilo potrebno: protokol napisan jednom u Javi, preslikan u Swift, iza jednog jedinog interfejsa izloženog kroz Turbo Module dok su Turbo Moduli još bili eksperimentalni.
Proizvod za daljinsku verifikaciju identiteta za njemačke finansijske institucije. Postojeći tok je bio sedam koraka fotografija, videa i gestova, i model računarskog vida koji odlučuje da li dokument pred kamerom izgleda vjerodostojno. Radilo je, a i dalje je bilo zaključivanje: model vjeruje da je ovo pravi pasoš.
Čip je druga vrsta odgovora. On predaje podatke koje je potpisala država izdavalac. Njegovo čitanje pomjera proizvod od procjene ka dokazu, i zato se isplatilo uraditi ga iako nije postojalo ništa čime bi se to uradilo.
Zašto ne biblioteka
Godine 2020. čitanje NFC čipa dokumenta iz React Nativea nije bilo dostupno ni u jednom paketu koji biste stavili pred banku. Apple je tek godinu ranije otvorio čitanje čipa aplikacijama trećih strana. Ono što je postojalo bilo je uglavnom nativno, uglavnom za Android, uglavnom neodržavano. Zato je protokol morao biti implementiran nativno i izložen JavaScript sloju.
Šta protokol traži od vas
Prvo iznenađenje za većinu ljudi je to što pasoš ne možete jednostavno prisloniti. Čip neće odgovoriti dok ne dokažete da fizički držite dokument, a tjera vas da to dokažete onim što je odštampano na stranici.
MRZ, sa odštampane stranice
└─ broj dokumenta + datum rođenja + datum isteka, svaki sa kontrolnom cifrom
└─ BAC / PACE — sesijski ključevi izvedeni tačno iz toga
└─ sigurni kanal: svaka komanda šifrovana i MAC-ovana, brojač sekvence
└─ DG1 podaci mašinski čitljive zone
DG2 slika lica
SOD potpisani heševi svake grupe podataka
└─ pasivna autentifikacija:
provjeri potpis države izdavaoca,
pa ponovo heširaj svaku grupu i uporediBAC izvodi sesijske ključeve iz mašinski čitljive zone, pa je redoslijed čitanja: prvo uzmi MRZ, optički ili otkucan, pa onda razgovaraj sa čipom. PACE je noviji mehanizam sa istom idejom i mnogo boljim dogovorom o ključu, otporan na offline napad koji dopušta BAC-ov ključ niske entropije. To koji ćete dobiti zavisi od dokumenta, pa prava implementacija podržava oba i pregovara.
Poslije toga sve ide preko sigurnog kanala sa brojačem sekvence, što ima praktičnu posljedicu: ako telefon usred posla izgubi polje, sesija je gotova. Ne nastavlja se, nego se kreće ispočetka, i interfejs to mora reći a da korisnik ne osjeti optužbu.
Pasivna autentifikacija je korak koji je bitan i korak koji većina implementacija preskoči. Sigurnosni objekat dokumenta sadrži heš svake grupe podataka, potpisan od države koja je izdala pasoš. Provjera tog potpisa i ponovno heširanje onoga što ste pročitali jeste razlika između čitanja čipa i vjerovanja čipu. Preskočite je i imate zgodnu prečicu za unos podataka koju falsifikator može popuniti.
Jedan interfejs, dvije nativne implementacije
Protokol je razrađen i napisan u Javi za Android. iOS verzija je ista ta logika prepisana u Swift sa istim ponašanjem — nije projektovana po drugi put. React Native je vidio jedan zajednički interfejs kroz Turbo Module, sa dvije nativne implementacije iza njega.
To preslikavanje je bilo namjerno. Dvije nezavisne implementacije ICAO čitača razići će se na rubnim slučajevima — neuobičajena grupa podataka, dokument koji nudi samo PACE, konvencija kontrolne cifre — a rezultat je da isti pasoš prolazi na jednom telefonu a pada na drugom. To je zahtjev podršci na koji se ne može odgovoriti, a korisnikov zaključak je da je vaša aplikacija pokvarena, što i jeste.
Na JavaScript strani ništa od ovoga nije vidljivo. Jedan poziv, tipiziran rezultat, tipizirane greške:
// oblik toga, u današnjim terminima API-ja
export interface Spec extends TurboModule {
readDocument(key: {
documentNumber: string
dateOfBirth: string // YYMMDD, iz MRZ-a
dateOfExpiry: string
}): Promise<{
mrz: string // DG1
portrait: string // DG2, base64
passiveAuth: 'valid' | 'failed' | 'unavailable'
}>
}Dekodiranje podataka koji su sišli sa čipa bilo je onda klijentov vlastiti eksterni API, ne naš. Vrijedi to imenovati kao granicu: posao modula završava na „evo šta je čip rekao i da li se potpis održao“.
Turbo Moduli 2020.
Bili su tada eksperimentalni dio nove arhitekture React Nativea — uključivani ručno, oskudno dokumentovani, i godinama daleko od stabilnog izdanja. Izabrati ih za proizvod koji ide u finansijsku instituciju bilo je rano usvajanje u doslovnom smislu.
Ono što je to činilo odbranjivim jeste da je alternativa bila gora za ovaj konkretan posao. Čitanje čipa je razgovor sa stanjem, sa fizičkim predmetom u nečijoj ruci, osjetljiv je na latenciju, i pada na desetak razlučivih načina. Tipiziran interfejs generisan iz jedne deklaracije, umjesto labavo tipiziranih poruka koje se prenose preko starog mosta, pravi je oblik za to čak i kada je alat oko njega nezreo.
Dijelovi na koje vas niko ne upozori
Antena nije tamo gdje korisnik misli. Njen položaj se razlikuje od modela do modela telefona, a čip pasoša je u koricama ili na stranici sa podacima, zavisno od dokumenta. Ljudi drže pasoš iznad ekrana, jer su uputstva tamo. Ilustracija mora prikazati poleđinu telefona.
Čitanje traje sekunde, ne milisekunde. Dovoljno dugo da se ljudi pomjere, a pomjeranje završava sesiju. Interfejs mora zadržati pažnju kroz čekanje, i mora razlikovati „drži i dalje“ od „kreni ispočetka“.
Taksonomija grešaka jeste funkcionalnost. Pogrešan MRZ ključ, čip van dometa, tip dokumenta nije podržan, provjera potpisa nije uspjela — četiri različita problema, četiri različite stvari koje bi osoba trebala uraditi sljedeće, a samo jedna od njih je njena krivica. Njihovo sažimanje u „Dokument nije moguće pročitati“ pretvara rješiv trenutak u napuštenu prijavu.
Šta bismo sada uradili drugačije
Većinu toga. Danas postoje održavane biblioteke, nova arhitektura je stabilna, a čitanje čipa na iOS-u je obično. Kada bi isti zadatak stigao sutra, posegnuli bismo za onim što postoji i vrijeme potrošili na dijelove iznad, koji se nisu popravili.
Jedina odluka koju bismo ponovili jeste da se protokol napiše jednom i preslika. Kako god da izgleda sloj platforme, dva nezavisna čitanja istog standarda će se prije ili kasnije razići oko istog pasoša, a saznaćete to od osobe koja je već pokušala tri puta.
Ovo je proizašlo iz proizvoda za daljinski KYC za njemačke finansijske institucije, gdje je čitanje čipa dodato povrh sedmokoračnog toka verifikacije. Pročitajte studiju →