What's inside a non-EU country's vaccination QR Code?
A couple of weeks ago I read What’s Inside the EU Green Pass QR Code?. It was very interesting.
In the two weeks since I’ve gotten a look at the vaccination certificates from two non-EU countries: Bosnia from the entity of Republika Srpska (RS), and Serbia.
TL;DR: while the EU code embeds the certificate itself, the Bosnian (RS) QR code contains simplified data and a URL, while the Serbian contains only a URL.
The rest of article discusses the deficiencies of that approach.
Note that I do not focus on superficial visual aspects, but mostly on authentication.
- What’s inside the QR code
- The issues
- Data is not signed❗
- No scanner❗
- Issues with the domains and web applications
- Not including a photograph
- What does this mean?
- What is to be done?
What’s inside the QR code
The QR code is printed as part of the paper certificate. I will not link the paper certificate here.
The Bosnian (RS) QR code contains nearly all the information from the paper,
| delimited. It looks like this:
<INITIALS>|<CERT ID>|<VACCINE MANUFACTURER>|<FIRST DOSE DATE>|<FIRST DOSE BATCH>|<SECOND DOSE DATE>|<SECOND DOSE BATCH>|<URL>
The URL is hosted on
http://vakcinacija.javnozdravstvors.org/. I will obviously not show the full URL. But I will also not include the full path for reasons that will become obvious later.
The Serbian QR code is only a URL to
https://ws.rfzo.rs/ which redirects to
Here are the pages they link to:
Bosnian (RS) online vaccination certificate
Serbian online vaccination certificate preview -- full below
Personal information removed, of course.
Contrast this with the EU implementation where the QR code contains the certificate itself. It’s in base45, compressed and signed.
There are three categories of issues.
First, that the Bosnian (RS) QR code does not sign the embedded information.
Second, that there is no companion scanner app.
And third, the whole host of issues that arises from embedding just a URL.
In this section I will run through those issues and how they could be addressed.
Data is not signed❗
The Bosnian (RS) QR code actually contains the details from the certificate in the following format:
<INITIALS>|<CERT ID>|<VACCINE MANUFACTURER>|<FIRST DOSE DATE>|<FIRST DOSE BATCH>|<SECOND DOSE DATE>|<SECOND DOSE BATCH>|<URL>
But this does not contain a signature that authenticates this information.
That makes checking the information in the QR useless for validating authenticity.
A forged document can easily be made to contain the correct QR code.
Contrast that with the Austrian code where the signature is part of the code. In the screenshot below the yellow is data and green is the signature.
It’s important to note, however, that only if there was another field for the signature, this would have been a very good solution. Sure, it wouldn’t have been as technically “impressive” but it would have accomplished most of the same thing in a much simpler way.
But since the signature is not there, in order to really authenticate the document the URL must be checked.
Regardless of whether the entire certificate is embedded, or just the identifier, there should be a scanner app that can be trusted.
Without it, it falls on the person scanning the certificate to verify that the domain serving the validation is trusted.
And ensure the authenticity of the document the domain must be the correct one.
Having a person do this, rather than a program, introduces a potential avenue for fraud. There are several (easy) ways that the domain can be made to look legitimate.
A very simple way to solve this is to embed just the identifier in the QR code. The scanner app can read the identifier and redirect to the correct certificate. That would not require any cryptography and would solve many potential issues.
Even though many certificates have already been issued, the scanner can easily be made backwards compatible. It could work with already issued documents by parsing the existing format and just extracting the ID. In case of the Bosnian (RS) format, that would mean the value before the first
|. In the Serbian format that would mean extracting the parameter from the embedded URL.
An even simpler version of the scanner can just check whether the embedded URL is on a list of pre-approved domains.
Issues with the domains and web applications
Since there is no signature in the QR code and there is no scanner, the domains and the web applications introduce several issues.
SSL certificates do not verify the Organization
Two of three domains use LetsEncrypt. LetsEncrypt is a great start since it encrypts traffic.
However, in such an important scenario there is an additional need to authenticate the identity of the organization running the service.
Some certificate authorities, including LetsEncrypt, do not do that. They test whether an organization controls a domain, but do not confirm the identity.
As you can see in the screenshots below the Organization and Organization Unit are not part of the certificate even for the website that uses a commercial provider.
Bosnian (RS) site SSL certificate
Serbian site SSL for vaccination confirmation
Serbian site SSL for the certificate
Note that for
.gov domains this isn’t a big issue because they’re restricted.
Contrast that to the Austrian websites where the certificate is issued to the Ministry of Health indicating that they indeed own the service.
Austrian scanner SSL
Austrian ministry SSL
Using .org domains
A project of this importance should be using a
.gov domain and Serbia indeed uses it. Bosnia RS, however, uses
.org TLD looks quite credible but it is actually unrestricted.
The domain was originally “intended as the miscellaneous TLD for organizations that didn’t fit anywhere else”. It is commonly used by non-profit organizations, open-source projects, and communities, but is an open domain that can be used by anyone.
This is a problem because if someone is looking to forge a certificate they can register a similar looking
.org domain and it would look quite legitimate.
Here are just a couple of domains that are very similar to
http://vakcinacija.javnozdravstvors.org/ that are still available for registration.
The Austrian sites use a
Domains are too long
Domain length isn’t an issue in itself. But because these systems rely on a user verifying that the web page is served from the correct domain, long names become a significant disadvantage.
The issue is that the domain can be set as a subdomain. For instance, I can set up https://vakcinacija.javnozdravstvors.org.different.org. On a mobile browser the domain will look very similar.
Even though Chrome switched to always showing the last part of the domain, in this case only
different indicates that this is a subdomain with
.org introducing a degree of legitimacy.
Ideally, they should be served from easy to memorize, short, domains that would be visible in their entirety in the address bar.
Interestingly, the Serbian certificate actually uses a
.rs URL from another service. That URL then redirects to the
.gov site. There is some potential for exploitation here should the domain be taken over or lapse, but that’s not extremely likely.
I am, however, curious about the reasoning to use another domain for seemingly no other purpose than as link shortener. Perhaps they wanted to have smaller QR codes?
Using sequential integer IDs
The identifier in the Serbian is a hash of some sort. There is no way to enumerate it.
The Bosnian (RS) certificate website however uses integer IDs. Not only are they simple integers but they’re also sequential. Therefore, it’s trivial to enumerate through them and download all certificates.
While there are no ID numbers in the page private data is still exposed. If you know someone’s initials and date of birth, you can ascertain if they’ve been vaccinated and where with a high degree of certainty.
This should obviously be replaced with a hashed identifier of some sort.
This is the first reason why I have not linked to the full URL of the Bosnian (RS) certificate.
Not having the complete certification information
In order to fully authenticate the document all the information on the paper must match the web page. However, neither of the documents contain all the information.
The text above refers to a page that is for confirming vaccination but not from an official “certificate”. The certificate does contain the full information.
Click on image to view in full
Here is the the Bosnian (RS) document again:
Compared to the paper document, some personal information (full name and gender) is removed. Only initials and the date of birth remain. This means documents could technically be shared by people sharing initials. Combining initials with date of birth is probably accurate enough provided that the date of birth is indeed checked every time.
It seems a bit strange to me, however, that full name and gender are excluded.
It’s as if it was a privacy consideration given the sequential ID numbers.
It’s also interesting the the Bosnian (RS) paper document did not contain the person’s ID number.
No robots or meta noindex
What’s quite surprising is that neither site has a
robots.txt. Nor does the individual certificate have a
<meta name="robots" content="noindex">. That might end up being a problem if links were published.
This is the second reason I’m not sharing the full URL.
Requiring Internet access to validate
The EU version embeds the entire certificate and the signature. This means that apps can be made for authorized users that have the signing key and can verify the certificate without internet access.
In the case of the non-EU version the certificate is not in the QR code therefore internet access is required for verification.
This not only means that they’re less convenient and slower but introduces a potential privacy issue.
Each venue would have to connect to the central server. As a result, it would be possible to trace an individual’s movements by checking which IP addresses queried for a particular certificate.
nit: QR codes can be scanned with any device with a camera
Not including a photograph
It’s interesting that none of the certificates (EU and non-EU) have a photograph. This seems a bit strange to me and I’m very curious as to why.
Not having a photograph makes the certificate less useful. Without it, in order to ensure that the person holding the code is the same as the person in the document their ID must be checked.
When dealing with secure areas where government is involved, such as border crossings, this might not be an issue. An individual’s ID will be checked anyway.
But, if the certificates are to be used at other venues, such as in hospitality or at events, I highly doubt it would be feasible to check every visitors ID.
It’s definitely a privacy consideration to potentially publicly expose people’s photos. However, with a scanner app, the photos could be available only to the authorized scanner users.
What does this mean?
It means that there is a desire to embrace tech.
The governments recognize it’s value.
They want to be able to provide a similar service to their citizens.
But, at the same time, it seems that they don’t have the resources. While they almost definitely do not have the same level of funding as the EU, they also lack the expertise. Bosnia and Serbia are very aware of their issues with brain-drain. Their most talented people are moving to the EU, in fact.
What is to be done?
Fix the obvious
The immediate fixes to most of these issues are quite straightforward and would not require a lot of effort. Given that they’re government projects, however, there is the bigger question of available resources versus how important these projects are to the government.
If I had to guess, I’d say that the sequential IDs will be fixed but I doubt the existing certificates would be re-issued. and the Serbian certificate will get more information.
EU to share the tech
A more idealistic solution, that I would like to see, is for the EU to provide a assistance with the implementation of their system.
I imagine that the benefits provided to the would-be members would far outweigh the investment required on part of the EU.
There are two approaches that could be considered.
Include other countries in the EU system
I would imagine that the the EU system is quite robust. As a result, I think onboarding other countries, and particularly prospective members would only be a political matter.
This would be a great benefit to the region since they would be participating in a real EU process.
For the EU this would help because they’d be training future member states in how things are done in the EU both from a technical and political perspective.
Facilitate others forking the tech
I recognize that onboarding other countries to the EU system might be a hard sell politically. So the alternative might be to let the region run a fork of the system.
One approach might be for the EU to provide a somewhat senior contact person who would be able to guide or perhaps lead a regional team comprising of members from each Balkan country.
They could be employed by the government, potentially from educational institutions, or on loan from the private sector. They would run the service and provide local training.
Hosting could be a potential cost but it might be possible to engage the telecoms or the private sector to provide is as part of their CSR.
This would result in a few quite significant benefits.
- It would train local talent for running a public sector tech project under EU leadership.
- It would create a system that’s compatible with the EU version that would further facilitate travel.
- It would be a nudge in the Mini-Schengen direction.
- It would foster collaboration in the region
- And it would be great for diplomacy
I do concede that I do not work in government so I almost definitely do not understand the complexities of the political and bureaucratic processes that might be at play here.
Do you know someone in government who might make this happen? Please ask them to consider this.
Montenegro has announced that it’s implementing the EU certificate which will be valid locally but will apparently be integrated with the EU version as well. Announcement (not in English) is here..
Get in touch
Or send me feedback. It will take less than 20 seconds.