Verifying the Turkish ID validity the hard (or easy?) way
How does a Turkish ID work anyways
The Turkish ID Card, aka TCKK, is a smartcard, quite an interesting one actually. It has two separate chips for contact and contactless. Both run a locally developed smartcard OS (AKİS/“Akıllı Kart İşletim Sistemi”, lit “Smart Card Operating System”). It can theoretically use a locally developed IC (UKTÜM), but none of my IDs so far had it.
The contactless interface
On the contactless (NFC) interface, it's an ISO/IEC 14443A based ICAO 9303-compliant eMRTD (Electronic Machine Readable Travel Document). I've done quite a bit of work recently to add eMRTD support to Proxmark3 and it can read my ID perfectly, but that's a blog post for another day.
The contact interface
On the contact interface, however, it's a completely different beast: It's based on a number of Turkish Standards , and it's seemingly quite secure.
It has various applets like ID verification, e-signature (both by your identity, and your dedicated e-imza cert, though latter wasn't deployed yet I believe) and emergency health information. Sadly, however, it's not well documented publicly (other than some exceptions , and all these cool features are simply... unused.
Dumping the cert
I've dumped my first TCKK cert on my first ever TCKK back in 2018 by sniffing USB communications, and wrote a tool to automate it back in 2019 when I renewed my ID to get my image updated, and finally got to use it again when I got a new ID in 2020 after I lost my wallet in Leipzig after 36c3 .
Anyhow, today I open sourced that script and another one. I'll probably be publishing more over there in the future, especially as I understand ISO/IEC 7816-4 and ASN.1 better after implementing ICAO 9303, so I will simply go over using that.
This isn't intended to be a “TCKK verification for the masses” post, so I'll skip through the simple details.
Clone TCKKTools, install python3.6+, install dependencies, plug in your favorite contact smart card reader (I use an ACS ACR39U), put in your ID with the chip facing up. You'll likely also want to install
openssl as we'll be using that for converting the certificate and verifying it.
python3 dumpcert.py, and it should dump your certificate as a file called
You can convert the cert from der to pem with
openssl x509 -in cert.der -inform der -out cert.pem.
You can view certificate details with
openssl x509 -in cert.pem -text.
Verifying the cert 
First off, ensure that you converted the certificate to
pem format and that you have openssl installed.
Secondly, let's grab the required files. Download the following URLs (do be aware that the .crl url is fairly big, around 350MB):
So... there's an odd thing where kokshs is a der and kyshs is a pem file (where kyshs lacks a newline on the file ending), so the procedure is a little odd. In any case...
# Convert CRL to a PEM
openssl crl -inform DER -in kyshs.v1.crl -outform PEM -out crl.pem
# Add a newline to kyshs.v1.crt
echo "" >> kyshs.v1.crt
# Convert the kokshs.v1.crt file to a PEM
openssl x509 -in kokshs.v1.crt -inform der -out kok.pem
# Join intermediary cert with root cert to create a cert chain
cat kyshs.v1.crt kok.pem > chain.pem
# Join chain and CRL into a single CRL chain
cat chain.pem crl.pem > crl_chain.pem
Additionally, you may have issues verifying the certificate as the CRL at the time of writing has expired (roughly 2 weeks ago), so we'll be skipping CRL expiry checks. If this is no longer the case in the future (see  for more info on how you can check), drop the
-no_check_time. See  for more info on what happens if you run without that.
To verify the certificate, run this command:
openssl verify -no_check_time -crl_check -CAfile crl_chain.pem cert.pem
It should take a while, but it will go through the whole CRL and verify your TCKK cert's validity.
If you see a message like this, then your TCKK certificate is valid:
However, if you see one like this, then it isn't:
C = TR, serialNumber = 1234568902, CN = ACAR HASAN
error 23 at 0 depth lookup: certificate revoked
error cert2017.pem: verification failed
I've been curious if my old ID certificates that I was keeping around were in the long, long CRL that govt publishes, but only got around to checking today. It was nice to see that they were indeed in there.
I've also been meaning to publish some of the TCKK research I made, and publishing this and the two scripts over at TCKKTools feels good. I look forward to publishing more stuff.
This is just one of the many ways to verify the identity of someone using the TCKK. This may not be a legally acceptable way of verifying someone's ID for actual commercial purposes (I simply haven't checked them).
1: TS 13582, TS 13583, TS 13584, TS 13585, TS 13678, TS 13679, TS 13680, TS 13681.
2: Funny story actually. I got through the whole event without losing anything, then dropped my wallet in Leipzig Hbf at an Aldi. Almost missed my flight searching it. Called my banks on Sbahn to cancel my cards. When I got to the airport there was a “Final Call” for me, Turkish Airlines staff warned me that I was late but that they'd let me through, and airport staff practically pushed me to the front of the passport line. Border control dude still took his sweet time counting the amount of days I spent in Germany before finally letting me through. I was the last to board. I ended up getting my NVI date while taxiing to gate on Istanbul Airport. But in the end everything ended up working out and I ended up getting everything reissued, which is okay I guess.
4: There's apparently a person called Furkan Duman who's working on a company developing ID verification technologies who's posted some tidbits in Turkish on his blog, I didn't get a chance to read stuff very much so far, but they look quite interesting: https://furkanduman.com/blog/category/tckk
openssl crl -in crl.pem -text -noout | grep "Next Update". You can safely Ctrl-c after the first output, otherwise it'll go through the whole file for no good reason. If the shown date is past current date, then the CRL has expired.
6: Running without
-no_check_time leads to a rather confusing output from openssl. You still get the same output when feeding it invalid certificates, but you also get
error 12 at 0 depth lookup: CRL has expired. However, on valid certificates, while you don't get
error 23 at 0 depth lookup: certificate revoked like you do on invalids, you still get the CRL has expired line, and that leads to a verification failure, which ends up being a little confusing.
7: Huge shoutouts to linuxgemini for informing me this was possible (and overall sparking my interest in smartcards and RFID tech) and showing me how to do it on a cold election day in Ankara when I flew back to vote.