Structured content
core/paragraph
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.
core/paragraph
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.
core/paragraph
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:
core/list
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.
core/heading
How can this work ?
core/paragraph
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.
core/paragraph
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.
core/heading
Technical details
core/paragraph
Here is what a test certificate looks like:
core/paragraph
As you can see, there are two barcodes in two different formats:
core/list
A QR code containing the text https://bonjour.tousanticovid.gouv.fr/app/wallet?v=DC04FR03AHP11E691E69B201FRF0OPHIR%1DF1LOJKINE%1DF216041994F3MF4945006%1DF5NF6240420210929%1F7N6GCZR3FHC3JL2WYDE4LQ3GHG7TJAK3U6RLBPZJYHK43KJDJA32RUZTXG2LVDKNVYXFL6YPP2TPWMVGPB3H7MNZUTE7X3GN3RZHCUY
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).
core/paragraph
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:
core/table
ScreeningVaccinationFirst nameLast nameBirth DateSexBirth DateAnalysis codeName of the diseaseAnalysis resultProphylactic agentVaccineVaccine makerRank of the last vaccination state (1st or 2nd dose)Total expected number of dosesDate and time of the testDate of the last vaccination stateVaccination state
core/paragraph
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.
core/paragraph
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)
core/paragraph
If you want more details about the data format, my beautiful TypeScript implementation of it is on github.
core/paragraph
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.
core/paragraph
But starting from that, can we implement what seemed to be the initial goal stated in the government's document ?
core/heading
Preventing event organizers from seeing too much data
core/paragraph
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 ?
core/paragraph
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.
core/paragraph
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.
core/paragraph
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.
core/paragraph
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 !
core/paragraph
If you find something and disclose it responsibly, I'll credit you in the about page.
core/paragraph
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.