eu-digital-green-certificates / dgc-participating-countries

All contents and information for onboarding representatives of participating countries.
Apache License 2.0
25 stars 16 forks source link

Make approved trust list publicly accessible #10

Closed mauimauer closed 3 years ago

mauimauer commented 3 years ago

Why would you put the master trust list behind mTLS auth? Priority should be assigned to distributing a verifiable trustlist to everyone who wishes to validate the contents of DGCs. The certificates/pkeys are not sensitive and should be made accessible to everyone.

If you don't want to serve this via an API at least consider hosting a static daily dump (+ signature) of the trustlist in a publicly accessible location.

jbx1 commented 3 years ago

@mauimauer great. I presume KIDs and public keys are enough for QR code verification.

dslmeinte commented 3 years ago

Just for fun, I made a small web app (no server side components, everything happens on the frontend) that can read and verify EU DCC and UK NHS COVID Pass QR codes:

https://covid-pass-verifier.com/

In case it's useful for anyone the list of certificates (140 as of now) it uses is here:

https://covid-pass-verifier.com/assets/certificates.json

This JSON was generated from the CBOR encoded trust list provided by the Austrian Government's Greencheck app. Example element from the JSON:


{

  "kid": [211,107,221,0,230,63,250,2],

  "crt": [48,130,4,223,48,...,174,204,152],

  "iss": {

    "C": "LU",

    "O": "INCERT public agency",

    "CN": "Grand Duchy of Luxembourg CSCA"

  },

  "sub": {

    "C": "LU",

    "O": "Ministry of Health",

    "CN": "Grand Duchy of Luxembourg DS DCC 3"

  },

  "pub":{

    "x": [228,75,88,108,235,190,70,229,28,...,210,156,153,82],

    "y": [243,124,19,188,214,49,246,...,42,248,201,81,33,63]

  }

}

Excellent! Is the source code publicly available? I'm asking for two reasons:

skounis commented 3 years ago

Great Job!

I'm also interested in its source code. I did start working in past on the something similar for demonstrating the scanning of a QR code. It could be great if we combine our efforts.

dslmeinte commented 3 years ago

I made https://dcc-crosscheck.vercel.app/ - mind that those rules are not the official rules on the DCC Gateway, and no rights can be derived from using that site! Source code here: https://github.com/dslmeinte/dcc-crosscheck

skounis commented 3 years ago

@dslmeinte @bcsongor Should we join forces and start working on a web application just for demonstrating purposes? I believe it will help us communicate rapidly experiences and ideas and capture early feedback.

dirkx commented 3 years ago

Lovely work ! Would be nice to combine the work of you 3 !

bcsongor commented 3 years ago

@dslmeinte @skounis @dirkx Superb idea, would love to join forces.

I published the source code of my web app and also updated the certificates as it indeed didn't include the UK public keys—sorry for this.

Source code: https://github.com/bcsongor/covid-pass-verifier (I might have sacrificed some CS best practices on the altar of speed, please look at it from a distance 🙈)

Certificates: https://covid-pass-verifier.com/assets/certificates.json

COVID Pass Verifier is certainly not feature complete and apart from checking the COSE signature there's no other validation against any ruleset. It also lacks support for test and recovery groups, only the vaccination group is supported as of today.

lovasoa commented 3 years ago

Hello everyone ! I had an issue on sanipasse's automatic certificate fetching from the french backend. The backend usually returns full x509 certificates, with a subject and an issuer that allow knowing where the certificate comes from.

But since today, it also returns two additional KIDs for which it provides only an ECDSA public key, without a certificate:

I could add these keys to sanipasse too, without certificate information, but I'm a little suspicious. Does any of you know where these KIDs come from and why they are not associated with a certificate ?

bcsongor commented 3 years ago

Hey @lovasoa, I believe these KIDs and public keys are for the UK certificates. @mauimauer found a project using these keys but I couldn't find the full certificates either and it looks like the repo has been taken down since then. Fortunately I was able to incorporate these (and a couple more UK-related keys) into https://covid-pass-verifier.com/assets/certificates.json just before the repo got deleted/hidden.

I have a UK-issued COVID pass and was able to verify that the public keys match with the signature in the CWT.

jbx1 commented 3 years ago

Are those the only 2 UK public keys? I thought the file in the original link had more for the same KID. Unfortunately I didn't take a copy of them. Does anyone have them in the format as expected by the dgc verifier app?

tschudin commented 3 years ago

For the current Europe-wide list of DCC keys from a Swiss vantage point, see the ch-dcc-keys repo and its data directory.

Because of MITM concerns (as pointed out above by @vaizki ) we check the signature from the Swiss Government (i.e., BIT/Bundesamt für Informatik) that is applied to the exported list of keys and let others check for themselves that this is the official list: Python code to do so is included.

dirkx commented 3 years ago

NL does exactly the same - except we publish it into a CDN at https://verifier-api.<acc/test/etc>.coronacheck.nl/v4/verifier/public_keys -- and we sign it the same sort of way as CH.

Extract with curl URL | jq -r .payload | base64 -d. | jq. For efficiency reasons we only expose the public keys (X/Y of the Q on an EC curve), the keyId and class validity. Not the full cert.

bcsongor commented 3 years ago

@tschudin, @dirkx Thanks a lot for making these public!

In other news, here are the official UK public keys: https://covid-status.service.nhsx.nhs.uk/pubkeys/keys.json — still no certificates unfortunately.

panzi commented 3 years ago

Is there a signature and root certificate from a different source to verify the UK public keys?

Also: I hope this wasn't posted here already and I couldn't find it, but Norway seems to use the same QR-code format except with an NO1: prefix instead of HC1: and these public keys: https://koronakontroll.nhn.no/v2/publickey Although you need a token to access them. More info here: https://harrisonsand.com/posts/covid-certificates/

@dslmeinte @bcsongor Maybe you want to support Norwegian certificates, too? See also my EHC verification Python script that can also be used to just download trust lists (AT, CH, DE, FR, NL, NO, SW, UK) and save them in a CBOR (full x509 certificates only) or JSON format (pub keys+not valid before/after) (both formats defined by me): https://github.com/panzi/verify-ehc It might or might not be of help to you.

tschudin commented 3 years ago

@bcsongor the kid field in the UK list is interesting: the values are not according to the EU spec (but serve the purpose, so I see no problem here). The KeyId values provided show that a counter is involved. Here are the UK kid values in hex:

4b6579315245
4b6579325245
4b6579335245
4b6579345245
4b6579355245
4b65793150524f
4b65793250524f
4b65793350524f
4b65793450524f
4b65793550524f

while the EU document "eHealth Network / Guidelines on Technical Specifications for Digital Green Certificates / Volume 1 / V1.0.5 / 2021-04-21" says:

A.1 The Key Identifier (kids) The key identifier (kid) is calculated when constructing the list of trusted public keys from DSC certificates and consists of a truncated (first 8 bytes) SHA-256 fingerprint of the DSC encoded in DER (raw) format.

tschudin commented 3 years ago

Three days ago @lovasoa wrote:

But since today, it also returns two additional KIDs for which it provides only an ECDSA public key, without a certificate:

* `S2V5MVJF` (public key 

... I could add these keys to sanipasse too, without certificate information, but I'm a little suspicious. Does any of you know where these KIDs come from and why they are not associated with a certificate ?

As @bcsongor wrote, these seem to be UK keys as they are now accessible via the URL that he gave: https://covid-status.service.nhsx.nhs.uk/pubkeys/keys.json.

The site is only domain-verified via let's encrypt, btw, so this seem to be the most "certification" you can get. Certificate Transparency for governments still needs to be invented ...

stapelberg commented 3 years ago

See also my EHC verification Python script that can also be used to just download trust lists (AT, CH, DE, FR, NL, NO, SW, UK) and save them in a CBOR (full x509 certificates only) or JSON format (pub keys+not valid before/after) (both formats defined by me): https://github.com/panzi/verify-ehc It might or might not be of help to you.

It would be great if you could contribute the trust list fetch logic to https://github.com/section42/hcert-trustlist-mirror, too, where a number of countries are already mirrored :)

dirkx commented 3 years ago

@Csongor -- no need for the certificates - see the specification. They key-id is al that is in the DCC. And all you need to verify the certificate with is the public key. Both of which are, for example, in the UK or NL trust lists / key lists.

dirkx commented 3 years ago

On 19 Jul 2021, at 08:26, Michael Stapelberg @.***> wrote:

It would be great if you could contribute the trust list fetch logic to https://github.com/section42/hcert-trustlist-mirror https://github.com/section42/hcert-trustlist-mirror, too, where a number of countries are already mirrored :

@Michael - would there be a nice way to merge this into https://github.com/ehn-dcc-development/ehn-sign-verify-python-trivial - so we can check 'anything against any country their idea of something' ?

stapelberg commented 3 years ago

@michael - would there be a nice way to merge this into https://github.com/ehn-dcc-development/ehn-sign-verify-python-trivial - so we can check 'anything against any country their idea of something' ?

I’m not affiliated with that repository, only a user of it :)

I’m using the trustlist mirrors programmatically in https://pkg.go.dev/github.com/stapelberg/coronaqr/trustlist/trustlistmirror

I think a good first step would be to use a common format for all lists (so that you don’t need multiple decoders), but then obtaining the list is as simple as doing an HTTPS request, so it should be easy enough to integrate.

dirkx commented 3 years ago

On 19 Jul 2021, at 10:01, Michael Stapelberg @.***> wrote:

@michael https://github.com/michael - would there be a nice way to merge this into https://github.com/ehn-dcc-development/ehn-sign-verify-python-trivial https://github.com/ehn-dcc-development/ehn-sign-verify-python-trivial - so we can check 'anything against any country their idea of something' ?

I’m not affiliated with that repository, only a user of it :)

Right - but I am - and happy to accept any pull request and/or figure out a way by which the two can levarage a common format or each other. I’m using the trustlist mirrors programmatically in https://pkg.go.dev/github.com/stapelberg/coronaqr/trustlist/trustlistmirror https://pkg.go.dev/github.com/stapelberg/coronaqr/trustlist/trustlistmirror I think a good first step would be to use a common format for all lists (so that you don’t need multiple decoders), but then obtaining the list is as simple as doing an HTTPS request, so it should be easy enough to integra.

A pretty common format seems to be a JSON with the KID as the key and then a dict; with one being the public key.

Dw

panzi commented 3 years ago

There's already the format the gateway endpoint would return: https://eu-digital-green-certificates.github.io/dgc-gateway/#/Trust%20Lists/downloadTrustList

However, in order to use it with WebCrypto having public keys in JWK format instead of certificates/public keys in DER/PEM Format is more useful. My Python script can generate JSON files that are useful for WebCrypto. It's not documented at the moment, though. My format doesn't include a way to verify the trust list against a signature and root certificate, though.

Also to note: IIRC some trust lists only provide public keys, but also include the not valid before/after timestamps. (Hope I don't misremember this.) And other trust lists also provide full trust chains that can to be verified down starting with the country's root certificate (Switzerland).

panzi commented 3 years ago

On 19 Jul 2021, at 08:26, Michael Stapelberg @.***> wrote: It would be great if you could contribute the trust list fetch logic to https://github.com/section42/hcert-trustlist-mirror https://github.com/section42/hcert-trustlist-mirror, too, where a number of countries are already mirrored : @michael - would there be a nice way to merge this into https://github.com/ehn-dcc-development/ehn-sign-verify-python-trivial - so we can check 'anything against any country their idea of something' ?

My script more or less started out with the trivial example, though it's not trivial anymore (and probably should be split to multiple files now). The first thing I added was support for RSA public keys, because the trivial Python example only supports elliptic curves, but there are some countries that use RSA.

dirkx commented 3 years ago

You can extract/find the RSA code in

 https://github.com/ehn-dcc-development/ehn-sign-verify-python-trivial <https://github.com/ehn-dcc-development/ehn-sign-verify-python-trivial> - 

It is this commit:

https://github.com/ehn-dcc-development/ehn-sign-verify-python-trivial/commit/68ece5f71e0f29ec6391d3e51bb5be905741b1c6

And tested agains the current trust list which has 3 RSA entries.

Dw.

panzi commented 3 years ago

Oh I see. Haven't looked at it after I started writing my own. 😄

lovasoa commented 3 years ago

There has been a bunch of new public keys without certificate added to the french backend: https://github.com/lovasoa/sanipasse/pull/30/files : S2V5MlJF, S2V5M1BSTw=, S2V5MlBSTw==, S2V5M1BSTw==, S2V5NFJF... Are these all from the UK ?

jbx1 commented 3 years ago

Seems so yes:

https://covid-status.service.nhsx.nhs.uk/pubkeys/keys.json

panzi commented 3 years ago

@bcsongor the kid field in the UK list is interesting: the values are not according to the EU spec (but serve the purpose, so I see no problem here). The KeyId values provided show that a counter is involved. Here are the UK kid values in hex:

4b6579315245
4b6579325245
4b6579335245
4b6579345245
4b6579355245
4b65793150524f
4b65793250524f
4b65793350524f
4b65793450524f
4b65793550524f

while the EU document "eHealth Network / Guidelines on Technical Specifications for Digital Green Certificates / Volume 1 / V1.0.5 / 2021-04-21" says:

A.1 The Key Identifier (kids) The key identifier (kid) is calculated when constructing the list of trusted public keys from DSC certificates and consists of a truncated (first 8 bytes) SHA-256 fingerprint of the DSC encoded in DER (raw) format.

I just noticed that the UK public key IDs are actually ASCII:

Hexadecimal    / Base64       / ASCII
4b65793150524f / S2V5MVBSTw== / Key1PRO
4b6579315245   / S2V5MVJF     / Key1RE
4b65793250524f / S2V5MlBSTw== / Key2PRO
4b6579325245   / S2V5MlJF     / Key2RE
4b65793350524f / S2V5M1BSTw== / Key3PRO
4b6579335245   / S2V5M1JF     / Key3RE
4b65793450524f / S2V5NFBSTw== / Key4PRO
4b6579345245   / S2V5NFJF     / Key4RE
4b65793550524f / S2V5NVBSTw== / Key5PRO
4b6579355245   / S2V5NVJF     / Key5RE

Noticed that when debugging something and Python printed a bytes key ID like so:

>>> b64decode("S2V5M1BSTw==")
b'Key3PRO'

Wonder if that means the *PRO keys are actual production keys and the *RE keys are... what? Research? Are they not to be used in a production environment?

panzi commented 3 years ago

The French trustlist seems to include both kinds of UK keys, but none of the Austrian, Swiss, German, Dutch, Norwegian, or Swedish trustlists include any of those keys.

dirkx commented 3 years ago

This is indeed a deviation. Interestingly enough - they have found a 'loophole' - this happens to work - as the KID is just an 8 byte array really. And as long you provide a mapping in your version of the trustlist (rather than expect the verifier to derive it from the original PEM, if any) - it works.

asitplus-pteufl commented 3 years ago

Hi all, I am following this discussion since it started, and I am seeing a problem here: The trustlist should not only list the public keys, but should also guarantee that the information is complete and correct and only "to-be-trusted" certificates are stored in the trustlist. Now, we do not have one trustlist but many from different member states, those member states might not have the same view on which certificates are included and which are not (either due to technical reasons or policy/org reasons). Also, certain member states might decide to extend their national trust lists with other certificates for national use cases (in Austria, we planned for that, we wanted to tag the certs in the trustlist as EU-wide and some as AT-Only for national use cases). If someone interprets this information in a wrong way, national certificates (or certificates from other use cases) could then end up in a EU-wide trust relation (in the AT case - if it would have been implemented - this could have meant that certain tests that are only valid for national use cases would end up as EU-trusted tests).

To conclude:

Solutions:

panzi commented 3 years ago

Yes, I'd wish the trust lists would follow a standard, had some sort of tagging, and would be publicly documented (the German one is). Some trust lists have a way to be verified using a root key, but e.g. in the Austrian case the only place I know where to find that root key is in JavaScript served by the same server as the trust list itself. I do extract and use that root key in my script, but it would be nice if it would be served as-is (not embedded in JavaScript) from some (multiple) other servers. And official documentation would be nice too. Just in case you're somehow involved with the Austrian solution. 😄

asitplus-pteufl commented 3 years ago

@panzi for the austrian solution, this documentation and the procedure for onboarding is just worked out (I think you have my email address, send me a note I can forward you the current PDFs for that), austria will publish the trustlist, the business rules and the value sets for the apps. for the business rules we will also publish the national AT rules and most likely meta-information for the various profiles (entry, night-clubs, etc.)

panzi commented 3 years ago

Anyone interested in a comparison between which public keys are available in which trust list? The value in the cell is the subject country name as know to the trust list it is from. If the trust list doesn't know that information it is just X.

certs_table.txt

Generated with my verify_ehc.py script: ./verify_ehc.py --certs-table AT,CH,DE,FR,GB,NL,NO,SE (with a few tokens extracted from various apps as environment variables)

Interesting that the Netherlands have a lot of public keys no one else has.

dirkx commented 3 years ago

Would be useful to sent this list every week to the interoperability meetings at 12:00 - @Milan - what would the options be to have this reported

About NL - I suspect some systemic thing in how we do the KID (wrong/different). Will get investigated.

ryanbnl commented 3 years ago

@panzi you need to use the production endpoint:

https://unshit.nl/?shit=https://verifier-api.coronacheck.nl/v4/verifier/public_keys

not acceptance:

https://unshit.nl/?shit=https://verifier-api.acc.coronacheck.nl/v4/verifier/public_keys

panzi commented 3 years ago

@ryanbnl Thank you! Fixed.

ryanbnl commented 3 years ago

Thanks. It's an orthogonal issue, but it would be great to see this running against PROD/ACC for as many countries as possible. So we can check that accidents don't happen.

stapelberg commented 3 years ago

for the business rules we will also publish the national AT rules and most likely meta-information for the various profiles (entry, night-clubs, etc.)

Is this available already?

I was trying to find sources for each country’s covid business rules (as per https://github.com/ehn-dcc-development/dgc-business-rules), but the Swiss endpoint only provides rules for Switzerland.

Maybe we should have a list/mirror for business rules, just like https://github.com/section42/hcert-trustlist-mirror/ is for the trustlist?

dslmeinte commented 3 years ago

@stapelberg You might want to check out https://github.com/eu-digital-green-certificates/dgc-business-rules-testdata which serves as a development/staging area for business rules. Note that these are not synced with the DCC Gateway, precisely to keep it useful for development purposes.

Also possibly interesting: https://dcc-crosscheck.vercel.app/

stapelberg commented 3 years ago

Thanks, I’m aware of the testdata and my implementation already passes it :)

I’m still interested in getting the live rules from somewhere, though

panzi commented 3 years ago

I noticed that many of the X.509 certificates of various countries seem to be using wrong OIDs in the extended key usage extension. They have an extra .0 component at some point (e.g. 1.3.6.1.4.1.0.1847.2021.1.1 Vs 1.3.6.1.4.1.1847.2021.1.1).

Countries with these wrong OIDs:

DK, RO, BG, SK, LV, MT, NO, SI, FI, GR

Countries that use the OIDs from the spec:

LI, DE, IS, PL, PT, AT, BE, FR, IE, VA, CY, EE, CZ, HR, LV, LU, IT, LT, SE, CH

The spec: https://github.com/ehn-dcc-development/hcert-spec/blob/main/hcert_spec.md#a4-extended-key-usage-identifiers

Don't know how to pass on that information to the various countries, and don't know if that can be fixed in existing certificates. Thought I post that here just in case there are the relevant people reading this thread.

bhavin-qryptal commented 3 years ago

Don't know how to pass on that information to the various countries, and don't know if that can be fixed in existing certificates. Thought I post that here just in case there are the relevant people reading this thread.

I believe a new published version of https://ec.europa.eu/health/sites/default/files/ehealth/docs/digital-green-certificates_v1_en.pdf should/could address this. This document is still referring to incorrect (with extra 0) Usage Identifiers.

panzi commented 3 years ago

I also found these weird key usages in some of the certificates:

  Count OID
     21 1.3.6.1.5.5.7.3.2 clientAuth
     20 1.3.6.1.5.5.7.3.4 emailProtection

I interpret those as not having any usage IDs and as such fall back to having all three.

bhavin-qryptal commented 3 years ago

I also found these weird key usages in some of the certificates:

  Count OID
     21 1.3.6.1.5.5.7.3.2 clientAuth
     20 1.3.6.1.5.5.7.3.4 emailProtection

I interpret those as not having any usage IDs and as such fall back to having all three.

by rule, such certificates should be considered as invalid for DCC verification. Isn't it?

panzi commented 3 years ago

These unexpected extended key usage object IDs are all from Spain (C=ES). I don't see any X.509 certificates from Spain that don't have these wrong extended key usages.

panzi commented 3 years ago

Ok now whoever is behind the FR trust list (which as the only non-GB one that I know includes the GB public keys) seems to had the idea to fake X.509 certificates for the GB public keys. First they set C=UK (the correct 2 letter country code is GB) and secondly this means that calculating the fingerprint of that fake X.509 certificate gives a key ID that doesn't match what the trust list says it is.

I say fake certificate because the GB trust list only includes public keys, not actual X.509 certificates. Maybe they actually get the X.509 certificates directly from the UK or know a different trust list endpoint? Then it would be the UK itself that uses the wrong 2 letter code for their own country? In any case the mismatching key ID is annoying.

Thought that might be good to know to anyone that also uses that trust list.

PS: If someone working on the FR trust list reads this, you have a bug in an HTTP header: Last-Modified: {now} GMT

lovasoa commented 3 years ago

Yes, I noticed these strange changes here: https://github.com/lovasoa/sanipasse/pull/42/files There is also the CN=S2V5M1BSTw== which seems to indicate that they auto-generated the certificate...

EdossProject commented 2 years ago

Hi, who should I ask for European certificates? Italy etc ..?

daniel-eder commented 2 years ago

You should get in touch with the national health authority of the country you are operating your application in. The national backends will allow to verify certificates from other EU member states as well. @EdossProject