Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Where to get the Public Key with which the Trust List is signed? #157

Closed
panzi opened this issue Jul 6, 2021 · 8 comments
Closed

Where to get the Public Key with which the Trust List is signed? #157

panzi opened this issue Jul 6, 2021 · 8 comments

Comments

@panzi
Copy link

panzi commented Jul 6, 2021

The first line of the Trust List is a signature, but in order to verify that I'd need the public key (to the private key with which the signature was created). Where can I find that?

@timokoenig
Copy link
Member

@panzi https://github.com/Digitaler-Impfnachweis/covpass-ios/blob/main/Certificates/DEMO/CA/pubkey.pem

@panzi
Copy link
Author

panzi commented Jul 6, 2021

Thank you! Are you sure this is the right one, though? Because I'm getting this:

>>> import requests
>>> from cryptography.hazmat.primitives.asymmetric.ec import ECDSA
>>> from cryptography.hazmat.primitives.serialization import load_pem_public_key
>>> from cryptography.hazmat.primitives import hashes
>>> from base64 import b64decode
>>> certs_signed_json = requests.get('https://de.dscg.ubirch.com/trustList/DSC/').content
>>> pubkey_pem = requests.get('https://github.com/Digitaler-Impfnachweis/covpass-ios/raw/main/Certificates/DEMO/CA/pubkey.pem').content
>>> pubkey = load_pem_public_key(pubkey_pem)
>>> sign_b64, body_json = certs_signed_json.split(b'\n', 1)
>>> sign = b64decode(sign_b64)
>>> pubkey.verify(sign, body_json, ECDSA(hashes.SHA256()))
Traceback (most recent call last):
  File "<pyshell#167>", line 1, in <module>
    pubkey.verify(sign, body_json, ECDSA(hashes.SHA256()))
  File "/home/panzi/.local/lib/python3.9/site-packages/cryptography/hazmat/backends/openssl/ec.py", line 378, in verify
    _ecdsa_sig_verify(self._backend, self, signature, data)
  File "/home/panzi/.local/lib/python3.9/site-packages/cryptography/hazmat/backends/openssl/ec.py", line 106, in _ecdsa_sig_verify
    raise InvalidSignature
cryptography.exceptions.InvalidSignature

(Using PROD or PROD_RKI instead of the DEMO in the URL doesn't change anything.)

@e7p
Copy link

e7p commented Jul 7, 2021

Keep in mind that the verify method of hazmat.primitives.asymmetric.ec takes signatures in the DER encoded DSS format only. To achieve this format, add to the code:

from cryptography.hazmat.primitives.asymmetric.utils import encode_dss_signature
r = int.from_bytes(sign[:len(sign)//2], byteorder="big", signed=False)
s = int.from_bytes(sign[len(sign)//2:], byteorder="big", signed=False)
sign = encode_dss_signature(r, s)

@panzi
Copy link
Author

panzi commented Jul 7, 2021

Thank you! 😄

@e7p
Copy link

e7p commented Jul 7, 2021

@panzi maybe you are also interested in my Python port of the relevant kotlin code in the SDK to be able to verify and dump contents of CovPass QR-Codes. After all it is just a quick'n'dirty script which while writing helped me to understand the architecture of the system better. Another good read might be https://harrisonsand.com/posts/covid-certificates/

@panzi
Copy link
Author

panzi commented Jul 7, 2021

@e7p Thank you but I already did that part myself, see: https://github.com/panzi/verify-ehc
Note that I've also seen RSA keys being used, not just EC. My script handles that. What my script currently doesn't do is validating the signature of the trust list itself, but I know how to do that now (for Germany).

@loelkes
Copy link

loelkes commented Nov 24, 2021

I stumbled across this. Here's my solution, with some help from python-ecdsa:

import hashlib
from ecdsa import VerifyingKey
import requests

with open('pubkey.pem') as f:
    vk = VerifyingKey.from_pem(f.read())

result = requests.get(...)
signature, message = result.content.split(b'\n')
vk.verify(base64.b64decode(signature), message, hashfunc=hashlib.sha256)

@e7p
Copy link

e7p commented Nov 24, 2021

Looks like a good solution.
I thought I should eventually share the python snippet which is basically just the kotlin code ported to python: https://gist.github.com/e7p/66dde9002fcc0cb197f3bcab7c3ce975

As this is somehow just quick'n'dirty, it doesn't parse the signature so good as @loelkes solution though. It simply splits the signature in half to get the two parameters r and s.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants