Recently, there was a big debate here in France about whether we should have a health pass or not. A health pass (passe sanitaire) is a document that proves that you have been either vaccinated against or tested negative for COVID-19, and allows you to attend large events that were previously forbidden.

Last week, the national assembly voted in favor of such a system, and starting june the 9th, these passes will be mandatory for all gatherings with over a thousand attendees.

In the official announcement, on on the government’s website, they say that citizens will have to present the pass either as a printed document, or a code in the french government’s TousAntiCovid mobile application. And they pretend that depending on who scans the code, they will have access to a different set of information about it:

How can this work ?

If you think about it from a technical point of view, this seems a little hard to implement securely. Would you store the information in the pass itself, or in a database ? If you put it in the code, then how would you store the certificate’s date so that it can be used by event organizers to validate the entry to an event, but not accessed directly ? If you put it in a database, the implementation is easier, but you end up with a huge centralised database containing identifying information, test results, and vaccination records, which sounds risky, and would probably cause public outcry.

Now, the underwhelming moment: the actual implementation does not really address this issue. All the information is stored in clear text in the pass, and I made an open-source scanner that can read all the information in the pass, including the pieces that are supposed to be accessible only to the authorities and airline companies. When they said that event organizers cannot access all the information, they probably just meant are not supposed to.

Technical details

Here is what a test certificate looks like:

As you can see, there are two barcodes in two different formats:

The data is in the 2D-DOC format, for which we can find a specification in french on the website of the National Secured Titles Agency. This specification explains how to parse the code, and gives us the list of fields:

ScreeningVaccination
First name
Last name
Birth Date
SexBirth Date
Analysis codeName of the disease
Analysis resultProphylactic agent
Vaccine
Vaccine maker
Rank of the last vaccination state (1st or 2nd dose)
Total expected number of doses
Date and time of the testDate of the last vaccination state
Vaccination state

In order to prevent the data in the certificate from being falsified, these fields are followed by a base32-encoded signature, to be checked using the ECDSA algorithm. The list of accepted public keys can be found in the official TousAntiCovid application, so I added them to my implementation.

While studying the format and its implementation, I found and reported a security vulnerability in TousAntiCovid, but that’s a story for another time. (Follow me on twitter)

If you want more details about the data format, my beautiful TypeScript implementation of it is on github.

So, at this point, we have implemented a reader for the code, and everyone can now check everyone else’s code, and have access to all the fields in it.

But starting from that, can we implement what seemed to be the initial goal stated in the government’s document ?

Preventing event organizers from seeing too much data

Ideally, I would want to be able to let organizers validate my presence to their events, but not sending them a single bit of information they do not need. As we’ve seen, it’s not possible if we just present the QR codes on our test and vaccination certificates. So what can we do about it ?

We need an intermediary. If I could have something between me and the event organizer, trusted by both of us, that could on one side check my QR code, and on the other side validate my attendance to the organizer, I wouldn’t need to show my entire certificate directly to the organizer. So that’s what I built.

I built a small open-source website, where you can create new events, specify a list of invitees (with their first and last names), and send them a validation link. From that link, they can confirm their attendance, but only if they have a valid health pass.

From a technical point of view, it’s a SvelteKit isomorphic web application, which uses the same code on the frontend and the backend to check the sanitary passes. In the backend, it has a small SQL database which stores no personal information: just the list of invitees and their status.

Security

The security of such an application is quite critical, so I tried to keep it as simple and small as possible. I don’t have the means to run a bug bounty, but if you like information security, come and white hack me !

If you find something and disclose it responsibly, I’ll credit you in the about page.

That’s all for today. I hope you found the dive into french government tech interesting, and if you have friends in france, don’t hesitate to spread the word about Sanipasse.