使用openSSL验证欧盟绿色通行证

3

我刚刚收到了我的 Covid Green Pass。我开始解码了,这里是我得到的字段:

header: a20448349a42b0c2d0728e0126
payload: a4041a645d8180061a61053b9501624954390103a101a4617681aa62646e01626d616d4f52472d3130303033313138346276706a313131393334393030376264746a323032312d30372d313462636f624954626369782630314954303544314444
signature: 6f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc782cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a

在这个例子中,所有字段都是十六进制的。有效负载是CBOR结构,可以进一步解码以获取数据。

验证GreenPass

现在我想要做的是使用Unix工具openssl验证签名。 我发现绿色通行证签名是使用椭圆曲线数字签名算法(ECDSA),结合SHA-256哈希算法和P-256参数创建的。

使用openssl,我应该能够验证此GreenPass:

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

我需要三个参数:public_key_itmy_signaturemy_data

  • public_key_it 是一个包含公钥的文件,可用于检查绿色通行证签名。可在线获取,例如在意大利:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnL9+WnIp9fvbcocZSGUFlSw9ffW/jbMONzcvm1X4c+pXOPEs7C4/83+PxS8Swea2hgm/tKt4PI0z8wgnIehojw==
-----END PUBLIC KEY-----
  • my_signature 是一个包含绿码签名部分的文件。 我可以通过以下方式获取它:
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

有些字符无法打印,因此在这里再次以十六进制表示:

846a5369676e6174757265314da20448349a42b0c2d0728e012640590137a4041a645d8180061a61053b9501624954390103a101a4617681aa62646e01626d616d4f52472d3130303033313138346276706a313131393334393030376264746a323032312d30372d313462636f62495462636978263031495430354431444444393531343734423143393344313631413446343636334238452333626d706c45552f312f32302f31353037626973764d696e69737465726f2064656c6c612053616c7574656273640162746769383430353339303036636e616da463666e74664455504f4e5462666e664455504f4e5463676e74781f434f52454e54494e3c4e49434f4c41533c4d415249453c4652414e434f495362676e7822434f52454e54494e2c204e49434f4c41532c204d415249452c204652414e434f49536376657265312e302e3063646f626a313937382d31312d3137

好的,如果我尝试上面的openssl命令,我会得到:

$ 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

有什么提示吗?我是否在正确的轨道上?谢谢。
编辑:我现在解决了这个问题。我在博客文章中写了所有细节:http://www.corentindupont.info/blog/posts/Programming/2021-08-13-GreenPass.html

1
是的,P1363编码中的ECDSA-256签名为32个字节的R和32个字节的S,您可以在这里找到很多关于如何将其转换为OpenSSL可接受的DER签名的问题,但我对OpenSSL / Unix不够熟悉,无法做到这一点 - 这里是Java链接(https://stackoverflow.com/a/61873962/8166854),由@dave_thompson_085编写 - 祝你好运。 - Michael Fehr
1
@MA1 链接已经修复。所有内容都在这里解释了:http://www.corentindupont.info/blog/posts/Programming/2021-08-13-GreenPass.html - cdupont
@MA1 公钥的官方存储库在欧盟范围内并不存在。每个国家可以决定是否发布公钥,但这有点混乱... - cdupont
@cdupont 我在你的博客文章下面的评论中添加了更多细节。 - MA1
1
嘿,@EdmondTamas,我刚刚把它放回去了。 - cdupont
显示剩余13条评论
1个回答

2

在@MichaelFehr的帮助下,我成功解决了这个问题!

签名转换

GreenPass的签名是以“原始”(P1363)格式呈现的。然而,openssl只接受DER格式。因此我们需要进行转换。

以下是我的签名:

6f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc782cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a

这是一个64字节长的数据。它由两个整数R和S组成,其中R占据前一半,S占据后一半。

R = 6f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc78
S = 2cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a

根据DER编码,我需要添加一些额外的字节:
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

如果我进行组装,就可以获得我的DER签名:
echo -n "304402206f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc7802202cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a" | xxd -r -p > my_signature.der

数据转换

数据部分也需要组合。

根据COSE规范,我需要从Green Pass数据构建一个“Sig_structure”。该“Sig_structure”用于创建和验证签名。

以下是已完成的“Sig_structure”:

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

我们现在可以创建my_data:
echo -n "846a536967..." | xxd -r -p > my_data.bin

现在它可以工作了!

$ openssl dgst -sha256 -verify public_key_it -signature my_signature.der my_data
Verified OK

你也解决了“40590137 - 一些分隔符...不确定”的部分吗?我应该如何构建我的Sig_Structure? - jumpjack
@jumpjack,我在我的博客文章中解释了一切:http://www.corentindupont.info/blog/posts/Programming/2021-08-13-GreenPass.html - cdupont
我也在那里给你写了,还有一些不清楚的地方:“your mileage can vary”这句话让人感到迷惑,我怎么能确定字符串的最终长度呢? - jumpjack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接