Documentation of the QR code found on new Austrian ID cards.

Overview

Austrian ID Card QR Code

This document aims to be a complete documentation of the format used in the QR area on the back of new Austrian ID cards (Personalausweis) issued after 2nd of August 2021. The launch was acompanied by the introduction of the CHECK-AT app to cryptographically verify the data contained in the code. Unfortunately there is no public documentation of its format and the app is proprietary and obfuscated. The official website claims an open source release is being evaluated, but considering the technology is developed by a private company, youniqx Identity AG, which wants to sell it to other countries as well, I don't believe it will ever happen. I want publicly funded technology to be open source though, so I decided to make my own documentation, hoping anyone who's good at app development will pick it up and make one.

Sections of the QR Code

The QR code consists of 6 semicolon (;) separated sections. Some of them are padded with spaces. They are listed here in the same order as they are in the encoding.

Part 1: Signature

The signature is a base64 encoded hexstring where the first 64 hex characters represent the r value of an ECDSA signature and the last 64 characters represent the s number. Some crypto libraries want the r and s values individually, some as a concatenated bytestring and others as a DER encoded binary. You can create such a DER encoding using the ecdsa.util.sigcode_der function of the ecdsa Python module for example. Most crypto libraries have some way to convert signatures to and from DER encoding.

Part 2: IV

Another base64 encoded hexstring. It is only relevant for generating the signature data.

Part 3: Signature ID

Not really a signature ID, but that's what it's called in the code. It is actually a certificate identifier. Judging from the data we currently have, private keys will get rotated every couple of months and this identifier tells you which certificate to use. This is the only part that is not encoded in any way.

Part 4: MRZ

MRZ is the machine readable zone on the back of the identification card which is printed in big monospace letters and has lots of angle brackets. The format is well documented and human readable, so I will not be covering it in this document. This part is base64 encoded.

Part 5: Name

Full name in uppercase letters separated by newlines, also base64 encoded.

Part 6: Image

Very low-res version of the photo on the card in the rather obscure JPEG2000 format and again base64 encoded. JPEG2000 is not the same as the well supported original JPEG standard and might require specialized software to view. Writing the bytestream to a file with a .jp2 extension seems to be all that's needed to view the content in those programs though.

API

Intercepting the web traffic by the app there were a few API endpoints of which only one was actually useful. I'm documenting them all for completeness though. The app always sets the x-api-key header to 1Rrt0JmIUyHM6ARj, although this does not seem to be required to access the data. The key is hardcoded and I am not aware of any others.

Example request:

curl -H "x-api-key: 1Rrt0JmIUyHM6ARj" https://api.check-at.at/api/v1/certificates

/api/v1/ready

I don't really know what the point of this is. It just returns a success value.

Full URL: https://api.check-at.at/api/v1/ready

Example response:

{"success": true}

/api/v1/certificates

This endpoint returns the certificate data used to verify the signatures. The example response only lists one certificate, but there are multiple.

Full URL: https://api.check-at.at/api/v1/certificates

[{
  "certificate_id": "A16ATS004008",
  "public_key": "-----BEGIN PUBLIC KEY-----\nMIIBMzCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEAqftX26Huqbw+ZgqQ\nnYONcm479iPVJiAoIBNIHR9uU3cwRAQgfVoJdfwsMFfu9nUwQXr/5/uAVcEm3Fxs\n6UpLRPMwtdkEICbcXGzpSktE8zC12bvXfL+VhBYpXPfhzmvM3Bj/jAe2BEEEi9Ku\nuct+V8ssS0gv/IG3r7neJ+HjvSPCOkRTvZrOMmJUfvg1w9rE/Zf4RhoUYR3JwndF\nEy3tjlRcHVTHLwRplwIhAKn7V9uh7qm8PmYKkJ2DjXGMOXqjtWGm95AeDoKXSFan\nAgEBA0IABIFUQPj5oSWqeV7HqNKmQaUwEmChzR02q6K9Gjcr6UPjUdZAxd/51L2b\nyb1n0kFQoLMwEZBcUaF7G2LSfgLw6k0=\n-----END PUBLIC KEY-----",
  "valid_until": "2031-08-15T11:10:40Z"
}]

/api/v1/documents

Returns some kind of document directory. At the time of writing only has one entry.

Full URL: https://api.check-at.at/api/v1/documents

[{
  "document_id": 1,
  "name": "Personalausweis",
  "steps_updated_at": "2021-08-17T15:52:09.908791Z"
}]

/api/v1/steps/1

Lists the steps to manually check the ID card by the person using the app. It's unclear why this is even loaded because the content is unlikely to change so rapidly that it would warrant building an API for it.

Full URL: https://api.check-at.at/api/v1/steps/1

No example provided because it would take up too much space.

Cryptography

The signature algorithm is ECDSA with SHA256. The certificates use a brainpoolP256r1 curve.

Key Format

The certificates API returns PEM encoded public keys. They are not proper certificate because they are not signed by any entity and do not contain any of the usual attributes like a common name or expiration date. A function made for loading public keys has to be used instead of one for certificates.

Another pitfall is that the curve of the keys is encoded explicitly. This means that in addition to the public or private bits they contain each of the parameters that make up an elliptic curve. Very few tools and libraries seem to be able to deal with this format and instead expected a "named" curve where the parameters are given by a standardized name like nistp256 or brainpoolP256r1.

OpenSSL can be used to convert between the two key types. The -param_enc parameter of the openssl ec utility defines which format will be used. Details can be found in the manpage. An example command is given below:

openssl ec -pubin -in key_explicit.pem -param_enc named_curve -pubout -out key_named.pem

Signed Data

An important part of verifying signatures is getting a reproducible representation of the data to be signed. In this case it is comprised of the items listed below concatenated in order without any separation.

  • The IV value with the hex values decoded to binary
  • The signature ID encoded as ASCII
  • A single line feed (\n or 0x0A)
  • The MRZ data as decoded from base64
  • The name data as decoded
  • The image data as decoded

For an example check the provided Python code.

Demo usage

At first the certificates have to be fetched from the API. They will be placed in the directory certs. Another directory certs_named will also be created to be used later.

python3 fetchcerts.py

The script will tell you to convert the explicit certificates to named ones using a command like this:

openssl ec -pubin -in certs/A16ATS004008.pem -param_enc named_curve -pubout -out certs_named/A16ATS004008.pem

Be aware that while fetching and converting the certificates is a separate step, it should be repeated regularly because new certificates will very likely be added with time.

Now to get the data to be verified scan the QR code on the ID card and copy it to a text file. Whitespace is irrelevant and does not need to be preserved. I have named my file qr_data.txt. It can now be decoded and verified.

python3 verifydata.py qt_data.txt

OpenSSL usage

OpenSSL can use the original certificates without conversion. To try it modify the example to write sign_data to a binary file. I'll call it sign_data.bin in this example. Then convert the signature to DER which can be done using the following code and write it also to a file.

import ecdsa.util
signature_r = int(signature[:64], 16)
signature_s = int(signature[64:], 16)
signature_der = ecdsa.util.sigencode_der(signature_r, signature_s, order=None)

Then openssl can be called to verify the signature:

openssl dgst -sha256 -verify certs/A16ATS004008.pem -signature signature_der.bin sign_data.bin

License

  • CC BY 4.0
Owner
Gabriel Huber
Gabriel Huber
xeuledoc - Fetch information about a public Google document.

xeuledoc - Fetch information about a public Google document.

Malfrats Industries 651 Dec 27, 2022
EasyModerationKit is an open-source framework designed to moderate and filter inappropriate content.

EasyModerationKit is a public transparency statement. It declares any repositories and legalities used in the EasyModeration system. It allows for implementing EasyModeration into an advanced charact

Aarav 1 Jan 16, 2022
Variable Transformer Calculator

✠ VASCO - VAriable tranSformer CalculatOr Software que calcula informações de transformadores feita para a matéria de "Conversão Eletromecânica de Ene

Arthur Cordeiro Andrade 2 Feb 12, 2022
An MkDocs plugin to export content pages as PDF files

MkDocs PDF Export Plugin An MkDocs plugin to export content pages as PDF files The pdf-export plugin will export all markdown pages in your MkDocs rep

Terry Zhao 266 Dec 13, 2022
A simple malware that tries to explain the logic of computer viruses with Python.

Simple-Virus-With-Python A simple malware that tries to explain the logic of computer viruses with Python. What Is The Virus ? Computer viruses are ma

Xrypt0 6 Nov 18, 2022
Que es S4K Builder?, Fácil un constructor de tokens grabbers con muchas opciones, como BTC Miner, Clipper, shutdown PC, Y más! Disfrute el proyecto. <3

S4K Builder Este script Python 3 de código abierto es un constructor del muy popular registrador de tokens que está en [mi GitHub] (https://github.com

SadicX 1 Oct 22, 2021
Leetcode Practice

LeetCode Practice Description This is my LeetCode Practice. Visit LeetCode Website for detailed question description. The code in this repository has

Leo Hsieh 75 Dec 27, 2022
Python Tool to Easily Generate Multiple Documents

Python Tool to Easily Generate Multiple Documents Running the script doesn't require internet Max Generation is set to 10k to avoid lagging/crashing R

2 Apr 27, 2022
A curated list of awesome mathematics resources

A curated list of awesome mathematics resources

Cyrille Rossant 6.7k Jan 05, 2023
Your Project with Great Documentation.

Read Latest Documentation - Browse GitHub Code Repository The only thing worse than documentation never written, is documentation written but never di

Timothy Edmund Crosley 809 Dec 28, 2022
100 Days of Code Learning program to keep a habit of coding daily and learn things at your own pace with help from our remote community.

100 Days of Code Learning program to keep a habit of coding daily and learn things at your own pace with help from our remote community.

Git Commit Show by Invide 41 Dec 30, 2022
🐱‍🏍 A curated list of awesome things related to Hugo themes.

awesome-hugo-themes Automated deployment @ 2021-10-12 06:24:07 Asia/Shanghai &sorted=updated Theme Author License GitHub Stars Updated Blonde wamo MIT

13 Dec 12, 2022
Code and pre-trained models for "ReasonBert: Pre-trained to Reason with Distant Supervision", EMNLP'2021

ReasonBERT Code and pre-trained models for ReasonBert: Pre-trained to Reason with Distant Supervision, EMNLP'2021 Pretrained Models The pretrained mod

SunLab-OSU 29 Dec 19, 2022
Tutorial for STARKs with supporting code in python

stark-anatomy STARK tutorial with supporting code in python Outline: introduction overview of STARKs basic tools -- algebra and polynomials FRI low de

121 Jan 03, 2023
NoVmpy - NoVmpy with python

git clone -b dev-1 https://github.com/wallds/VTIL-Python.git cd VTIL-Python py s

263 Dec 23, 2022
Minimal reproducible example for `mkdocstrings` Python handler issue

Minimal reproducible example for `mkdocstrings` Python handler issue

Hayden Richards 0 Feb 17, 2022
pytorch_example

pytorch_examples machine learning site map 정리자료 Resnet https://wolfy.tistory.com/243 convolution 연산 정리 https://gaussian37.github.io/dl-concept-covolut

injae hwang 1 Nov 24, 2021
Test utility for validating OpenAPI documentation

DRF OpenAPI Tester This is a test utility to validate DRF Test Responses against OpenAPI 2 and 3 schema. It has built-in support for: OpenAPI 2/3 yaml

snok 106 Jan 05, 2023
Data Inspector is an open-source python library that brings 15++ types of different functions to make EDA, data cleaning easier.

Data Inspector Data Inspector is an open-source python library that brings 15 types of different functions to make EDA, data cleaning easier. Author:

Kazi Amit Hasan 38 Nov 24, 2022
Materi workshop "Light up your Python!" Himpunan Mahasiswa Sistem Informasi Fakultas Ilmu Komputer Universitas Singaperbangsa Karawang, 4 September 2021 (Online via Zoom).

Workshop Python UNSIKA 2021 Materi workshop "Light up your Python!" Himpunan Mahasiswa Sistem Informasi Fakultas Ilmu Komputer Universitas Singaperban

Eka Putra 20 Mar 24, 2022