How does the french health pass work ?
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:
- The authorities and airline companies' personnel will have access to all the information in the pass, including the certificate date, its type (vaccination or test), and in the case of a test, the result.
- Event organizers will have access only to the name and birth date of the subject, and whether the entry to the event was validated or not, based on the restrictions for the specific event. Nothing else. They will not be able to know whether the document is a PCR screening test result, or a vaccination certificate, for instance.
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.
Here is what a test certificate looks like:
As you can see, there are two barcodes in two different formats:
- A QR code containing the text
- A Data Matrix containing the same
information, but without the link:
DC04 FR03 AHP1 1E69 1E69 B2 01 FR F0 OPHIR \x1D F1 LOJKINE \x1D F2 16 04 1994 F3 M F4 945006 \x1D F5 N F6 24 04 2021 09 29 \x1F 7N6GCZR3FHC3JL2WYDE4LQ3GHG7TJAK3U6RLBPZJYHK43KJDJA32RUZTXG2LVDKNVYXFL6YPP2TPWMVGPB3H7MNZUTE7X3GN3RZHCUY(whitespaces added for legibility).
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:
|Analysis code||Name of the disease|
|Analysis result||Prophylactic agent|
|Rank of the last vaccination state (1st or 2nd dose)|
|Total expected number of doses|
|Date and time of the test||Date of the last 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.
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.