3

I just received my Covid Green Pass. I've started to decode it, here are the fields I get:

header: a20448349a42b0c2d0728e0126
payload: a4041a645d8180061a61053b9501624954390103a101a4617681aa62646e01626d616d4f52472d3130303033313138346276706a313131393334393030376264746a323032312d30372d313462636f624954626369782630314954303544314444
signature: 6f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc782cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a

All fields are hexadecimals in this example. The payload is a CBOR structure, it can be further decoded to get your data.

Verifying the GreenPass

What I would like to do now, is to verify the signature using the Unix tool openssl. I figured out that the green pass signature is created with Elliptic Curve Digital Signature Algorithm (ECDSA), using the P–256 parameters, in combination with the SHA–256 hash algorithm.

With openssl, I should be able to verify this greenpass:

$ openssl dgst -sha256 -verify public_key_it -signature my_signature my_data

I need three parameters: public_key_it, my_signature and my_data.

  • public_key_it is a file containing the public key capable of checking the green pass signature. It is available online, for Italy it is:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnL9+WnIp9fvbcocZSGUFlSw9ffW/jbMONzcvm1X4c+pXOPEs7C4/83+PxS8Swea2hgm/tKt4PI0z8wgnIehojw==
-----END PUBLIC KEY-----
  • my_signature is a file containing the signature part of the green pass. I get it with:
echo "6f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc782cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a" | xxd -r -p > my_signature
jSignature1MH4Br&@Y7d]a;bIT9avbdnbmamORG-100031184bvpj1119349007bdtj2021-07-14bcobITbcix&01IT05D1DDD951474B1C93D161A4F4663B8E#3bmplEU/1/20/1507bisvMinistero della Salutebsdbtgi840539006cnamcfntfDUPONTbfnfDUPONTcgntxCORENTIN<NICOLAS<MARIE<FRANCOISbgnx"CORENTIN, NICOLAS, MARIE, FRANCOIScvere1.0.0cdobj1978-11-17

Some characters are not printable, so here it is again in hexadecimals:

846a5369676e6174757265314da20448349a42b0c2d0728e012640590137a4041a645d8180061a61053b9501624954390103a101a4617681aa62646e01626d616d4f52472d3130303033313138346276706a313131393334393030376264746a323032312d30372d313462636f62495462636978263031495430354431444444393531343734423143393344313631413446343636334238452333626d706c45552f312f32302f31353037626973764d696e69737465726f2064656c6c612053616c7574656273640162746769383430353339303036636e616da463666e74664455504f4e5462666e664455504f4e5463676e74781f434f52454e54494e3c4e49434f4c41533c4d415249453c4652414e434f495362676e7822434f52454e54494e2c204e49434f4c41532c204d415249452c204652414e434f49536376657265312e302e3063646f626a313937382d31312d3137

Well, if I try the openssl command above, I get:

$ openssl dgst -sha256 -verify public_key_it -signature my_signature my_data
Error Verifying Data
140529059103168:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:../crypto/asn1/asn1_lib.c:91:
140529059103168:error:0D068066:asn1 encoding routines:asn1_check_tlen:bad object header:../crypto/asn1/tasn_dec.c:1137:
140529059103168:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:309:Type=ECDSA_SIG

Any hint? Am I even on the right track?? Thanks

EDIT: I now solved the problem. I wrote about all the details in a blog post: http://www.corentindupont.info/blog/posts/Programming/2021-08-13-GreenPass.html

cdupont
  • 1,138
  • 10
  • 17
  • Are you sure it is a good idea to publish sensitive data (e.g. real name and birthdate) here and your blog? For my studies I used the public available demonstration data available here: https://github.com/eu-digital-green-certificates/dgc-testdata – Michael Fehr Aug 26 '21 at 17:20
  • @MichaelFehr Good point, I plan to change this. I don't think it is very sensitive data: my real name and brithdate are already accessible on my blog anyway. What I understand is that some imposter could use my QR code to get in a bar... Is that the concern? – cdupont Aug 26 '21 at 19:29
  • My concern is that a lot of services need a real name and a real birthday pointing to "one" person to verify - I won't publish my birthday worldwide :-) – Michael Fehr Aug 26 '21 at 21:10
  • Regarding your issue - the signature is in **P1363 encoding** that is "R | S", so you need to convert the signature from P1363 to DER encoding to verify with OpenSSL. The complete data set is in Base45 encoding (no typo, not Base64) and "ZIP"ed. It could be helpful for you to check the code of a real "Green Pass Check App" to follow the path (I did it for an Android app, and it can be painful...) – Michael Fehr Aug 26 '21 at 21:16
  • What I understand is that my signature is composed of two integers R and S? My signature is 128 bits. So that means the first 64 bits for R and the next 64 is for S? How to construct the DER from that? – cdupont Aug 26 '21 at 21:44
  • @MichaelFehr I'm using the code from this app: https://github.com/giuseppeM99/GreenPassVerifyBot/blob/master/greenpass.py and yes, it is painful :) – cdupont Aug 26 '21 at 21:48
  • 1
    Yes, an ECDSA-256 signature in P1363 encoding is 32 bytes for R and 32 bytes for S and you can find a lot of questions here on SO how to convert it to a DER signature that OpenSSL could accept, but I'm not familiar enough with OpenSSL / Unix on how to do it - here is link in Java (https://stackoverflow.com/a/61873962/8166854) written by @dave_thompson_085 - good luck. – Michael Fehr Aug 26 '21 at 22:04
  • @cdupont I tried to access the blog post link didn't work. – MA1 Oct 20 '21 at 15:26
  • @cdupont How did you manage to get header, payload and signature from the QRCode? Is there any java library to do that? – MA1 Oct 21 '21 at 12:56
  • 1
    @MA1 The link is fixed now. Everything is explained there: http://www.corentindupont.info/blog/posts/Programming/2021-08-13-GreenPass.html – cdupont Oct 21 '21 at 21:08
  • @cdupont Thank you! Is there an official repository to get the public key from? Is this an official one? https://github.com/lovasoa/sanipasse/blob/master/src/assets/Digital_Green_Certificate_Signing_Keys.json – MA1 Oct 25 '21 at 19:41
  • @MA1 there is no official repo for the public keys, EU wide. Each country can decide to publish one, though. It's a bit messy... – cdupont Oct 26 '21 at 15:42
  • @cdupont Thanks for the details! I tried the public key you posted on your sample and it worked as expected, but it didn't work on the vaccination sample below which is published by EU, none of the samples worked. Any thoughts? https://github.com/eu-digital-green-certificates/dgc-testdata/tree/main/IT – MA1 Oct 26 '21 at 15:47
  • @MA1 what did you do exactly? Maybe you can post details in the comment section on my blog post... – cdupont Oct 26 '21 at 16:31
  • @cdupont I added more details in a comment on your blog post. – MA1 Oct 26 '21 at 20:55
  • @cdupont your blog is down :( Any chance to get it back online? Thanks! – Edmond Tamas Dec 19 '21 at 20:35
  • 1
    Hey @EdmondTamas, I just put it back up. – cdupont Dec 20 '21 at 14:50
  • @cdupont thanks! Exciting stuff, can't wait to dive in :P – Edmond Tamas Dec 20 '21 at 15:02

1 Answers1

2

With the help of @MichaelFehr, I managed to solve this problem!

Signature conversion

The GreenPass has a signature in "raw" (P1363) format. However, openssl only accepts DER format. So we need to convert it.

Here is my signature:

6f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc782cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a

It is 64 bytes long. It is composed of two integers, R and S. R is the first half, while S is the second half.

R = 6f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc78
S = 2cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a

According to DER encoding, I need to add some more bytes:

30  -- fixed value for composed structure
44  -- size of everything that follows
02  -- fixed value for integer
20  -- size of the R integer
6f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc78  -- R
02  -- fixed value for integer
20  -- size of the S integer
2cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a  -- S

If I assemble it, I can obtain my DER signature:

echo -n "304402206f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc7802202cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a" | xxd -r -p > my_signature.der

Data conversion

The data part needs to be composed, too. According to the COSE spec, I need to build a "Sig_structure" from the green pass data. This Sig_structure is used both for creating the signature, and verifying it.

Here is the "Sig_structure" completed:

846a5369676e6174757265314d  -- "Signature1" in hexadecimals
a20448349a42b0c2d0728e0126  -- My header (see original post above)
40590137                    -- some separator... not sure
a4041a645d8180061a61053b9501624954390103a101a4617681aa62646e01626d616d4f52472d3130303033313138346276706a313131393334393030376264746a323032312d30372d313462636f62495462636978263031495430354431444444393531343734423143393344313631413446343636334238452333626d706c45552f312f32302f31353037626973764d696e69737465726f2064656c6c612053616c7574656273640162746769383430353339303036636e616da463666e74664455504f4e5462666e664455504f4e5463676e74781f434f52454e54494e3c4e49434f4c41533c4d415249453c4652414e434f495362676e7822434f52454e54494e2c204e49434f4c41532c204d415249452c204652414e434f49536376657265312e302e3063646f626a313937382d31312d3137 -- my payload (see above)

We can now create my_data:

echo -n "846a536967..." | xxd -r -p > my_data.bin

It now works!!

$ openssl dgst -sha256 -verify public_key_it -signature my_signature.der my_data
Verified OK
cdupont
  • 1,138
  • 10
  • 17
  • Did you also solve the "40590137 -- some separator... not sure" part? How exactly do I build my Sig_Structure? – jumpjack Nov 01 '21 at 15:58
  • @jumpjack I explain everything in my blog post here: http://www.corentindupont.info/blog/posts/Programming/2021-08-13-GreenPass.html – cdupont Nov 01 '21 at 22:18
  • I also wrote you there, there is still something not clear also there: the "your mileage can vary" sentence is disorienting, how can I be sure of the final length of the string? – jumpjack Nov 02 '21 at 07:40