使用OpenSSL进行数字签名验证


只怕再见是故人
2025-03-10 11:27:18 (10天前)
  1. 如何在Ruby中使用OpenSSL验证CMS / PKCS7消息?

PKCS#7消息用作

数字
</跨度>

签名
</跨度>
对于用户消息,所以我需要签署一个新的用户消息并验证传入的消息。

2 条回复
  1. 0# 無口君 | 2019-08-31 10-32



    简短的回答



    假设所有内容都定义为它们在您的代码段中,具有分离的签名,没有到受信任根的证书链,证书

    crt

    ,签名

    signed

    和数据

    data

    ,以下应该做你想要的:




    1. store = OpenSSL::X509::Store.new
      p7 = OpenSSL::PKCS7.new(signed.to_der)
      verified = p7.verify([crt], store, data,
      OpenSSL::PKCS7::DETACHED || OpenSSL::PKCS7::NOVERIFY)

    2. </code>


    (我没有测试过,YMMV)



    全文



    以下是我如何找到这个的完整故事,其中包含我所使用的所有资源的链接,因此如果您需要更多信息,您可以在某处查看。



    我们发现,看看OpenSSL :: PKCS7文档

    这一点点智慧






    PKCS7.new =&gt; PKCS7
    </强>



    PKCS7.new(string)=&gt; PKCS7
    </强>

    本课程中的许多方法都没有记录。




    一个快速的谷歌也没有改变任何东西。这表明我们将不得不采取更极端的措施。我们做一个

    Google代码搜索

    对于使用OpenSSL :: PKCS7验证签名的任何人。



    嗯。我们发现

    一些测试用例

    。非常好;至少它有单元测试,可以帮助显示功能确实有效,并提供它的工作原理演示。




    1. store = OpenSSL::X509::Store.new
      store.add_cert(@ca_cert)
      ca_certs = [@ca_cert]

    2. data = aaaaa\r\nbbbbb\r\nccccc\r\n
      tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs)
      p7 = OpenSSL::PKCS7::PKCS7.new(tmp.to_der)
      certs = p7.certificates
      signers = p7.signers
      assert(p7.verify([], store))
      assert_equal(data, p7.data)

    3. </code>


    那不算太糟糕。包装证书商店。对您的数据进行签名,然后从签名数据中创建一个新的OpenSSL :: PKCS7对象。然后,你可以打电话

    certificates

    在它上面提取它签署的证书链,

    signers

    提取签名者,和

    verify

    可以调用以验证签名是否有效。您似乎将包含可信CA证书的证书存储作为要验证的第二个参数传递。您可以通过调用来提取数据

    data

    在上面。



    但第一个论点意味着什么?在我们的测试用例中似乎没有人传递任何东西,只有第一个参数的空列表。嗯。一个谜。我们会回过头来看看。



    第三个,可选的,参数

    verify

    看起来像它用于

    验证分离的签名





    1. data = aaaaa\nbbbbb\nccccc\n
      flag = OpenSSL::PKCS7::BINARY|OpenSSL::PKCS7::DETACHED
      tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs, flag)
      p7 = OpenSSL::PKCS7::PKCS7.new(tmp.to_der)
      a1 = OpenSSL::ASN1.decode(p7)

    2. certs = p7.certificates
      signers = p7.signers
      assert(!p7.verify([], store))
      assert(p7.verify([], store, data))

    3. </code>


    回到第一个论点。当我们进行代码搜索时,我们发现的不仅仅是测试用例;我们还发现了一些其他用途。事实上,第二个似乎是

    使用第一个参数




    1.   # 'true' if signature was created using given cert, 'false' otherwise
    2. def match?(cert)
      @p7.verify([cert.raw_cert], @store, nil, OpenSSL::PKCS7::NOVERIFY)
      end

    3. </code>


    喔好吧。这是要检查的证书列表。现在有第四个参数,它似乎由标志组成。检查

    OpenSSL文档

    ,我们看到这个不直观的名称(使用NOVERIFY标志验证?)意味着您应该只检查传入的证书和签名中嵌入的证书的签名,而不是尝试针对您的可信CA存储验证整个证书链。



    这都是有用的信息,但我们有什么遗漏?值得庆幸的是,Ruby是开源软件,因此我们可以“使用源代码,Luke!”在谷歌代码搜索上乱七八糟之后,我们发现了

    的定义

    ossl_pkcs7_verify


    。一旦你超越了有些神秘的名字,代码就可以直接阅读;它基本上只是将其参数转换为OpenSSL可以理解的格式,并调用:




    1. ok = PKCS7_verify(p7, x509s, x509st, in, out, flg);

    2. </code>


    所以,它看起来像

    那’

    我们真正想要寻找文件的地方。




    描述




    PKCS7_verify()

    验证PKCS#7 signedData结构。

    P7
    </强>
    是要验证的PKCS7结构。

    证书
    </强>
    是一组用于搜索签名者证书的证书。

    商店
    </强>
    是一个值得信赖的证书商店(用于链验证)。

    INDATA
    </强>
    是内容不存在的签名数据

    P7
    </强>
    (这是分离的)。内容写入


    </强>

    如果它不是NULL。

    1. </p>
    2. <P>
    3. <strong>
    4. </强>
    5. 是一组可选的标志,可用于修改验证

    操作。

    1. </p>
    2. <P>
    3. <code>
    4. PKCS7_get0_signers()
    5. </code>
    6. 从中检索签名者的证书
    7. <strong>
    8. P7
    9. </强>
    10. 它确实如此
    11. <strong>
    12. </强>
    13. 检查其有效性或签名是否有效。该
    14. <strong>
    15. 证书
    16. </强>




    </强>
    参数与中的含义相同

    PKCS7_verify().








    完整的男人页

    更多细节。



    哦,作为旁注,我找到了

    这个警告

    在搜索时;它看起来像在Ruby 1.9中,并且可能在一些更高版本的Ruby 1.8中,该类已从冗余的OpenSSL :: PKCS7 :: PKCS7转移到OpenSSL :: PKCS7。




    1. warn(“Warning: OpenSSL::PKCS7::PKCS7 is deprecated after Ruby 1.9; use OpenSSL::PKCS7 instead”)

    2. </code>

登录 后才能参与评论