Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/panzi/verify-ehc
Simple Python script to decode and verify an European Health Certificate QR-code
https://github.com/panzi/verify-ehc
Last synced: 3 months ago
JSON representation
Simple Python script to decode and verify an European Health Certificate QR-code
- Host: GitHub
- URL: https://github.com/panzi/verify-ehc
- Owner: panzi
- Created: 2021-06-22T01:02:43.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2022-10-01T02:32:53.000Z (about 2 years ago)
- Last Synced: 2024-07-15T14:40:38.473Z (5 months ago)
- Language: Python
- Size: 171 KB
- Stars: 60
- Watchers: 11
- Forks: 17
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
Verify EHC
==========A simple Python script to decode and verify an European Health Certificate QR-code.
Note that the expiration date read from the EHC isn't expiration date of tests or
vaccinations as defined by EU or local law. In all examples I saw it is much longer.
Therefore you need to implement your own logic with the rules defined by your
government to get proper expirations dates.**NOTE:** If you ask me how to commit document forgery I'll forward your message to
the police. (Luckily it isn't possible to forge European Health Certificates because
it uses state of the art cryptography.)Norwegian COVID-19 Certificate
------------------------------This script also tries to support Norwegian COVID-19 certificates, which seem
to be the same as European Health Certificates except with an `NO1:` prefix
instead of an `HC1:` prefix. Though this is untested for lack of real life
examples. See also
[this blog post](https://harrisonsand.com/posts/covid-certificates/).Usage
-----```plain
usage: verify_ehc.py [--help]
[--certs-file FILE | --certs-from LIST | --certs-table LIST]
[--no-verify] [--no-key-id-check] [--list-certs]
[--print-exts] [--strip-revoked] [--save-certs FILE]
[--download-root-cert SOURCE[@FILENAME]]
[--download-all-root-certs] [--allow-public-key-only]
[--envfile FILE] [--fail-on-error] [--warning-as-error]
[--image]
[ehc_code ...]positional arguments:
ehc_code Scanned EHC QR-code, or when --image is passed path to
an image file.optional arguments:
--help, -h Show this help message and exit.
--certs-file FILE Trust list in CBOR or JSON format.
--certs-from LIST Download trust list from given country's trust list
service. Comma separated list, entries from later
country overwrites earlier.
See also environment variables.
Supported countries: AT, CH, DE, FR, GB, IT, NL, NO, SE
Note that the GB trust list only contains GB public
keys, so you might want to combine it with another.
If neither --certs-file nor --certs-from is given then
--certs-from=DE,AT is used as default.
--certs-table LIST Print table of trust list certificates showing where
which key ID is avaliable showing the country of the
certificate as it is known to the given trust list. "X"
means the certificate/public key is in the trust list,
but no country attribute is known for it.
--no-verify Skip certificate verification.
--no-key-id-check Disable check of key IDs.
Key IDs are suppost to be the first 8 bytes of the
SHA512 hash of the certificate, but some certificates
of non-EU countries don't adhere to that and give out
different key IDs.
--list-certs List certificates from trust list.
--print-exts Also print certificate extensions.
--strip-revoked Strip revoked X509 certificates.
This downloads the revocation list for each certificate
in the trust list(s), if the certificate has an
revocation list attribute. A lot of the certificates
have broken revocation list entries. Meaning for some
the attribute doesn't even parse, for others the given
URI points to a non-existing endpoint, a broken
endpoint, or the data returned from the endpoint is
broken.
Note that this has nothing to do with revocation of
European Health Certificates, it is only about
revocation of trust list entries.
--save-certs FILE Store downloaded trust list to FILE. The filetype is
derived from the extension, which can be .json or .cbor
--download-root-cert SOURCE[@FILENAME]
Download and store root certificate (or public key) of
SOURCE as FILENAME. If FILENAME is not given SOURCE.pem
is used. If FILENAME ends in ".pem" the certificate (or
public key) is stored encoded as PEM, otherwise it is
encoded as DER.
--download-all-root-certs
Download and store all root certificates (or public
keys) and store them in SOURCE.pem files.
--allow-public-key-only, --allow-pubkey-only
When writing the CBOR trust list format it usually
rejects entries that are only public keys and not full
x509 certificates. With this options it also writes
entries that are only public keys.
--envfile FILE Load environment variables from FILE. Default is
".env". Set this to an empty string to not load
environment varibles from a file.
--fail-on-error Turns every error into an exception.
--warning-as-error Turns every warning into an error.
--image ehc_code is a path to an image file containing a
QR-code.environment variables:
_ROOT_CERT Some of the trust lists are have signatures that can be
checked with a certain trust list specific root certificate
(or just public key in the case of DE). Instead of always
downloading these certificates you can just download them
once using --download-root-cert or
--download-all-root-certs and then supply them to this
script using environment variables. The environment
variable can be a path to a PEM or DER encoded certificate,
a PEM encoded public key, or the value of the environment
variable itself can be a PEM encoded certificate or public
key. You can use this to pin the root certificate.
Example:
./verify_ehc.py --download-root-cert SE@se_root_cert.crt
export SE_ROOT_CERT=se_root_cert.crt
./verify_ehc.py --certs-from SE --save-certs certs.cbor
Trust list sources for which root certificates are
supported:
AT, CH, DE, NL, SECH_TOKEN Downloading the Swiss (CH) trust list and root certificate
requires the environment variable CH_TOKEN set to a bearer
token that can be found in the BIT's Android
CovidCertificate app APK. See also:
https://github.com/cn-uofbasel/ch-dcc-keysFR_TOKEN Downloading the French (FR) trust list requires the
environment variable FR_TOKEN set to a bearer token that
can be found in the TousAntiCovid Verif app. See also
token_lite:
https://gitlab.inria.fr/tousanticovid-verif/tousanticovid-verif-ios/-/blob/master/Anticovid%20Verify/resources/prod/prod.plistNO_TOKEN Downloading the Norwegian (NO) trust list requires the
environment variable NO_TOKEN set to an AuthorizationHeader
string that can be found in the Kontroll av
koronasertifikat app APK. See also:
https://harrisonsand.com/posts/covid-certificates/Report issues to: https://github.com/panzi/verify-ehc/issues
```You can also use this tool to download the trust list as provided of one (or
more) of the supported countries and save it as JSON or CBOR:```bash
./verify_ehc.py --certs-from AT --save-certs austrian_trust_list.json
``````bash
./verify_ehc.py --certs-from AT --save-certs austrian_trust_list.cbor
```It is also possible to save both versions at once:
```bash
./verify_ehc.py --certs-from AT \
--save-certs austrian_trust_list.cbor \
--save-certs austrian_trust_list.json
```The CBOR version is in the same format as the CBOR part of the Austrian trust
list. The JSON version is in a format that is useful when used with the
WebCrypto browser API. I.e. it supplies the public keys as JSON Web Keys (JWK)
and the algorithm parameter object as needed by the WebCrypto API.**NOTE:** Some trust list endpoints (UK, FR, NL) return only public keys instead
of full x509 certificates for some or all entries. These are supported for EHC
verification (untested because of lack of examples), but because they're no real
x509 certificates a valid time range of `1970-01-01T00:00:00+00:00` to
`9999-12-31T23:59:59.999999+00:00` is used. When using `--save-certs` with a
CBOR file these public keys are skipped and an error message is printed for
each. You can use them when saving the trust list to JSON, though, because that
itself doesn't contain a full x509 certificate.### Trust List Verification
Some countries sign their trust-list using a root certificate. If that is
supported by a given trust-list this script will verify the signature when
downloading it. The root certificates don't need to be updated that often, so
you might want to download and "pin" them (use the downloaded root certificate).Example:
```bash
./verify_ehc.py --download-root-cert AT@saved_at_root_cert.pem
export AT_ROOT_CERT=saved_at_root_cert.pem
./verify_ehc.py --certs-from AT --save-certs trust_list.cbor
```You can use OpenSSL to check when the root certificate is due to renewal:
```bash
$ openssl x509 -text -in saved_at_root_cert.pem
...
Validity
Not Before: Jun 2 13:46:21 2021 GMT
Not After : Jul 2 13:46:21 2022 GMT
...
```Note that some countries don't provide actual root certificates, but only public
keys. These can be used to check the signature of a trust-list just as well, but
plain public keys don't include validity date ranges. I.e. I don't know when
to refresh those.Every country has their own trust-list format and way of signature verification.
Since this script saves trust-lists in a common format (and can merge several
trust lists into one) no matter the source there is no trust-list signature that
can be checked once loaded via `--certs-file`. Meaning the trust-list signature
check is only performed (and the root certificates are only used) when downloading
a trust-list via `--certs-from`.MIT License
-----------Copyright 2021 Mathias Panzenböck
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.