Back to Index

Reading Serbian ID cards with Golang

I am a little bit late with this post, but I feel it is good to publish it nevertheless.

Three weeks ago, I released the Baš Čelik, a program for reading ID cards issued by the government of Serbia. This program can read data from an ID card, and save it as a PDF which looks the same as a PDF produced by the official application. And believe me, in Serbia for some reason you need this PDF (or print of it) quite often.

Since the official application only works on Windows, and Baš Čelik works on Windows/Linux/macOS, Baš Čelik was well received in the local Unix community. Community response, which size surprised me a little, gave me the motivation to continue working on the application.

After the first release, I implemented reading of medical insurance cards, and I am currently finishing work for reading vehicle cards (both cards are also issued by the government). After I finish with this, I will try adding features that are related to the personal certificate on the ID card: changing the PIN code, validating data on the ID card, and using the personal certificate on the card to sign data.

Progress wasn’t easy, since I didn’t know anything about smart cards before (and to be honest, I don’t know much more now. whole smartcard world seems a mess). Some older similar projects (like jfreesteel) gave me useful insights. In the end, I had to use a lot of reverse engineering: I sniffed USB traffic with the Wireshark in order to see how the official app communicates to the card (and have more of this work to do for the planned features).

The application is written in Go, and language choice wasn’t an easy task. At the start, I knew that I want something that easily cross-compilers (at least for Unix systems), but also I knew I don’t want to use Electron. C/C++ doesn’t have proper tooling which makes rapid development (testing libraries) very hard. That left probably Rust and Go as a sensible choice. I went with the Go because it seemed that UI development is easier in it than in Rust. I am not sure now if I made the right choice, but that is a story for another time…