Verify EU GreenPass with openSSL

Viewed 2518

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

1 Answers

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
Related