如何使用带有自定义引擎的 OpenSSL 验证文件签名

gmi*_*ile 5 openssl verification digital-signatures

2017 年 12 月 28 日更新 \xe2\x80\x93 3

\n\n

OpenSSL DSTU 模块的作者慷慨地提供了OpenSSL+DSTU 实现的补丁并修复了该问题,并提供了进一步的帮助。

\n\n

我能够用这个命令首先完成我需要的事情:

\n\n
./apps/openssl smime -verify -noverify -in my_message.txt.p7s -engine dstu -inform DER\nengine "dstu" set.\nHello, world!\nVerification successful\n
Run Code Online (Sandbox Code Playgroud)\n\n

后来将证书链连接bundle.pem成 后,我能够执行以下操作:

\n\n
./apps/openssl smime -verify -CAfile bundle.pem -in /yo/my_message.txt.p7s -engine dstu -inform DER\nengine "dstu" set.\nHello, world!\nVerification successful\n
Run Code Online (Sandbox Code Playgroud)\n\n

2017 年 12 月 28 日更新 \xe2\x80\x93 2

\n\n

OpenSSL DSTU 模块的作者确认该模块目前无法正常工作 \xe2\x80\x93 https://github.com/dstucrypt/openssl-dstu/issues/2#issuecomment-354288000

\n\n

我想我必须到其他地方寻找合适的 DSTU4145 实现。我刚刚了解了一个 BountyCastle 项目,以及它的规范包括 DSTU-4145。我想除了编写一些 Java 代码来执行签名验证之外别无选择。

\n\n

2017 年 12 月 28 日更新 \xe2\x80\x93 1

\n\n

这是我的文件:

\n\n\n\n
\n\n

我有一个文件,由某人用他的私钥签名:signed_content.txt。我也有CA的证书。私钥和证书在某种程度上彼此相关。

\n\n

如何验证文件上的签名?

\n\n

这就是我正在做的事情:

\n\n
    \n
  1. 从证书中提取公钥(从权威机构获得):

    \n\n
    openssl x509 -pubkey -inform der -in PrivateCerts/CA-3004751DEF2C78AE010000000100000049000000.cer -noout -engine dstu > public_key.txt\n
    Run Code Online (Sandbox Code Playgroud)
  2. \n
  3. 尝试验证文件的内容:

    \n\n
    openssl rsautl -verify -in my_message.txt.p7s -inkey public_key.txt -pubin -engine dstu\nengine "dstu" set.\nopenssl (lock_dbg_cb): already locked (mode=9, type=18) at md_rand.c:387\nopenssl (lock_dbg_cb): not locked (mode=10, type=18) at dstu_rbg.c:87\nError getting RSA key\n139964169291424:error:0607907F:digital envelope routines:EVP_PKEY_get1_RSA:expecting an rsa key:p_lib.c:288:\n
    Run Code Online (Sandbox Code Playgroud)
  4. \n
\n\n

另外,如何提取签名文件的实际内容?

\n\n
\n\n

我的文件是否不正确?我可以查看它的 ASN.1 内容:

\n\n
openssl asn1parse -inform DER -in my_message.txt.p7s -i\n
Run Code Online (Sandbox Code Playgroud)\n\n

asn.1 结构看起来不错(老实说,我对 ASN.1 知之甚少):我可以看到一些有关组织和内容的字段。

\n\n

我正在使用DSTU 引擎(乌克兰加密标准),类似于 GOST(俄罗斯加密标准)。

\n

dav*_*085 0

openssl rsautl仅处理 RSA 算法,而不处理任何其他算法:不是 DSA、不是 ECDSA、不是 GOST、不是 DSTU 等。openssl pkeyutl -sign/-verify可以处理通过标准EVP接口可用的任何算法,您的引擎大概应该如此。

然而,大多数签名算法实际上是对数据的哈希值而不是原始数据进行签名。特别是,我看到 BouncyCastle 有几种使用 GOST3411(哈希)和 DSTU4145(以及带或不带 LE 又名 Little-Endian 编码)的签名方案。为此,您要么需要显式散列然后使用openssl pkeyutl,或者更容易地使用openssl dgst -$hashname -sign/-verify它为您组合它们。对于内置哈希,您可以将其缩写为openssl $hashname -sign/-verify,但我不知道这是否适用于引擎哈希。

无论如何,您几乎肯定不想将所有内容视为signed_content.txt数据,更不用说视为数据的哈希值了。如果它具有 ASN.1 结构,它可能包括签名数据(仅作为结构的一部分)加上签名值,以及可能的元数据甚至其他数据。如果它是一个通用结构,并且您发布asn1parse结果,并且您认为敏感的任何数据值被抑制,但所有元数据(例如 OID)完好无损,我或这里的其他人可能会识别它并提供建议。如果是常见的结构,CMS/PKCS7,OpenSSL命令行可以直接处理。