dajiaji / python-cwt

A Python implementation of CWT/COSE.
https://python-cwt.readthedocs.io/
MIT License
22 stars 8 forks source link

Some EUDCC certificates can't be decoded #195

Closed merlinschumacher closed 2 years ago

merlinschumacher commented 2 years ago

Hi,

I've got issues with some RSA type public keys for EUDCC decoding. I've tried the same certificate with https://github.com/panzi/verify-ehc, and it decodes the swiss certificate properly using the given certificate. Bildschirmfoto vom 2021-12-13 23-47-26

python-cwt returns a validation error for the RSA key. Most other keys seem to work.

The following is the offending key.

    "Ll3NP03zOxY=": {
        "serialNumber": "1479dce89e848ba6077c57b16f925eca",
        "subject": "C=CH, ST=Bern, L=Köniz, 2.5.4.15=Government Entity, 2.5.4.97=NTRCH-CHE-467.023.568, O=Bundesamt für Gesundheit (BAG), OU=GE-0220-BAG, OU=Taskforce BAG Covid-19, CN=COVID-certificate-CH-21-05",
        "issuer": "C=CH, 2.5.4.97=VATCH-CHE-221.032.573, O=Bundesamt fuer Informatik und Telekommunikation (BIT), OU=Swiss Government PKI, CN=Swiss Government Regulated CA 02",
        "notBefore": "2021-05-20T10:04:31.000Z",
        "notAfter": "2024-05-20T10:04:31.000Z",
        "signatureAlgorithm": "RSASSA-PKCS1-v1_5",
        "fingerprint": "a572445c2c1d3ced7689963caf2c0e763778c024",
        "publicKeyAlgorithm": {
            "hash": {
                "name": "SHA-256"
            },
            "name": "RSASSA-PKCS1-v1_5",
            "publicExponent": {
                "0": 1,
                "1": 0,
                "2": 1
            },
            "modulusLength": 2048
        },
        "publicKeyPem": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtk/51stJXU48RqD2lh4IdsxFrjlJfmTCrLr3cQNEXkrEoI3OEV8NnotE1RjVmQrqLTT04oxpWlcbMolXtJBtu3rOiLNwQvyVEbj/xSc6KT84Tp7GBo1P/kkunY+Vmab6HUCV/oGZYmsdiUP/OnTPX6Wy6delDhnrgHIDti73/TSsG7Zl1V6km7+KIkjAkVCEDkkUD7uffd4G+GBZ0B9F1KOT0IcFQNvDm0zlROVoGFlmPS8DWlrLHuIdMbB281uiDjcN+kNUt7rUyyj6TFgX9WCgEB/5mQBMRaaXK1zeDTaNkmC2S7IWxhMQsMBXJyAdbD9AnQOZc6XRjBauO7gz0wIDAQAB"
    },
dajiaji commented 2 years ago

Thanks for reporting. I'll check it out.

merlinschumacher commented 2 years ago

This certificate shows the bug and uses a decodable DCC. I'ts taken from the swiss example certificates. The swiss live ones are also the ones having the issues. Additional to some antigen test certificates. Note: I used freezegun to ensure the certificate is still valid to the system.

import cwt
from cwt import load_pem_hcert_dsc
from freezegun import freeze_time

# A DSC(Document Signing Certificate) issued by a CSCA
# (Certificate Signing Certificate Authority) quoted from:
# https://github.com/eu-digital-green-certificates/dgc-testdata/blob/main/CH/2DCode/raw/1.json
dsc = "-----BEGIN CERTIFICATE-----\n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\n-----END CERTIFICATE-----"

# An EUDCC (EU Digital COVID Certificate) quoted from:
# https://github.com/eu-digital-green-certificates/dgc-testdata/blob/main/CH/2DCode/raw/1.json
eudcc = bytes.fromhex(
    "d2844ea2013824044824bc6b7b7bd2c328a059010aa401624348041a64df7ede061a611d17de390103a101a4617681aa626369782775726e3a757663693a30313a43483a35303131383344333946334636343430384345374638374362636f62434862646e026264746a323032312d30382d3031626973781f42756e646573616d742066c3bc7220476573756e6468656974202842414729626d616d4f52472d313030303031343137626d706c45552f312f32302f313532356273640262746769383430353339303036627670674a30374258303363646f626a313936342d30332d3134636e616da462666e6653747564657262676e674d617274696e6163666e746653545544455263676e74674d415254494e416376657265312e332e3059010093f6f69d4bf26e4e24b4a4779bef00b12f754c6a4a81e620dd236fae6599d3def54db93749fe06c5bbaf361bc1030d7772bbf24cfa8bc0439e984520c3b768a72906c5046a823dbf1b2a1ab516437999b1df2e3322db3813f4557b8e1ed31773b03a3a0c7c87759fa213a07d9d2bff808cb09c97b4aeeb2e2a174c87905af96549c30e43765b0d8f4c0482bebd245450dd9e6cfeb642fe854288342db9d94b94fca4c6aa8261a472d5832aa7abbbaac61352698f111f495a7fefc36d9794767f897a198538b0a31d3faa16e0b7450891c8d08b5ee6b749515efad692bb8c5b9b9e4afcbb1de5ac58d651b5f358f67248bdaa3fbc7a77feb86d66c750f47dc2b6"
)
freezer = freeze_time("2021-08-19 12:00:01")
freezer.start()
public_key = load_pem_hcert_dsc(dsc)
decoded = cwt.decode(eudcc, keys=[public_key])
claims = Claims.new(decoded)
freezer.stop()
dajiaji commented 2 years ago

I checked it out, and it seems that the error occurs at the OpenSSL layer. https://github.com/pyca/cryptography/blob/main/src/cryptography/hazmat/backends/openssl/rsa.py#L279-L281

The error message is as follows: the salt length seems to be inappropriate:

code=67625096, lib=4, reason=136, reason_text=b'error:0407E088:rsa routines:RSA_verify_PKCS1_PSS_mgf1:salt length check failed'

Is it only Swiss certificates that cause the error? I will look into it a little more closely after tomorrow, but it looks like there is some sort of problem with the Swiss certificate.

merlinschumacher commented 2 years ago

It's seemingly some live Swiss certificates and a few others. I just picked this test certificate, because it exposes the specific problem. I'm assuming that there is some variant of the certificates that isn't covered. Furthermore, I will test more of the test certificates provided by the EU later. As I wrote before verify-ehc, which does the work of python-cwt mostly by foot, can verify and decode the certificates. So can the python-test provided with the test data from the EU.

dajiaji commented 2 years ago

but it looks like there is some sort of problem with the Swiss certificate.

It looks like I was wrong, and there is a problem with the following python-cwt code that specifies the salt length. https://github.com/dajiaji/python-cwt/blob/main/cwt/algs/rsa.py#L52

dajiaji commented 2 years ago

@merlinschumacher I added a workaround for the bug and released v1.5.1. Could you check it out?

merlinschumacher commented 2 years ago

It works! Thanks for your speedy help!