ruby 使用OpenSSL进行数字签名验证

ndh0cuux  于 12个月前  发布在  Ruby
关注(0)|答案(1)|浏览(95)

如何在Ruby中使用OpenSSL验证CMS/PKCS #7消息?
PKCS #7消息用作用户消息的数字签名,因此我需要对新的用户消息进行签名并验证传入的消息。我在documentation和google上没有找到任何有用的东西。我发现了一些用于签名的代码示例,但没有用于验证的代码:

signed = OpenSSL::PKCS7::sign(crt, key, data, [], OpenSSL::PKCS7::DETACHED)
ryhaxcpt

ryhaxcpt1#

简短回答

假设所有内容都像你的代码片段中那样定义,有一个分离的签名,没有到受信任根的证书链,证书crt,签名signed和数据data,下面应该做你想要的:

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

(我没有测试过,YMMV)

全文

这里是我如何找到这个的完整故事,与链接到我使用的所有来源,所以如果你需要更多的信息,你有地方去看看。
看看OpenSSL::PKCS7文档,我们发现了这一点智慧:

    • PKCS7.new => pkcs7**
    • PKCS7.new(string)=> pkcs7**

这个类中的许多方法都没有文档记录。
快速谷歌也没有发现任何东西。上面说我们要采取更极端的措施。让我们为任何使用OpenSSL::PKCS7验证签名的人做一个Google code search
嗯。我们找到一些测试案例。那很好至少它有单元测试,这可以帮助显示功能确实工作,并提供它如何工作的演示。

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

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)

还不算太糟创建证书存储区。对您的数据进行签名,然后从签名的数据创建一个新的OpenSSL::PKCS7对象。然后,您可以在其上调用certificates来提取签名所用的证书链,signers来提取签名者,verify可以被调用来验证签名是否有效。看起来您传递了包含受信任的CA证书的证书存储,作为要验证的第二个参数。你可以通过调用data来提取数据。
第一个论点是什么意思?在我们的测试用例中,似乎没有人为第一个参数传递任何东西,除了一个空列表。嗯。一个谜。我们稍后再谈这个问题。
verify的第三个可选参数看起来像是用于验证分离签名:

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)

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

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

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

啊,好的。这是一份要核对的证书清单。现在还有第四个参数,它似乎由标志组成。检查OpenSSL docs,我们看到这个不直观的名称(用NOVERIFY标志验证?)意味着您应该只根据传入的证书和嵌入在签名中的证书来检查签名,而不要尝试根据受信任的CA存储来验证整个证书链。
这些都是有用的信息,但我们还遗漏了什么吗?幸运的是,Ruby是开源软件,所以我们可以“使用源代码,Luke!“在Google代码搜索上做了一些手脚之后,我们找到了ossl_pkcs7_verify的定义。一旦你越过了有点神秘的名字,代码就相当容易阅读了;它基本上只是将其参数转换为OpenSSL可以理解的格式,并调用:

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

所以,看起来像that'是我们真正想要查找文档的地方。

描述

PKCS7_verify()验证PKCS#7 signedData结构。* * p7是要验证的PKCS7结构。* * certs是一组证书,用于搜索签名者的证书。* * store为可信证书存储(用于连锁验证)。如果内容不在p7中(即分离),则indata是签名数据。如果不为NULL,则将内容写入out**。

    • flags**是一组可选的标志,可用于修改校验操作。

PKCS7_get0_signers()p7检索签名者的证书,它检查证书的有效性或是否有任何签名有效。* * certsflags**参数与PKCS7_verify().中的含义相同
请参阅full man page以了解更多详细信息。
哦,顺便说一下,我在搜索时发现了这个警告;看起来像是在Ruby 1.9中,可能在Ruby 1.8的一些后续版本中,类已经从冗余的OpenSSL::PKCS7::PKCS7移动到了OpenSSL::PKCS7。

warn("Warning: OpenSSL::PKCS7::PKCS7 is deprecated after Ruby 1.9; use OpenSSL::PKCS7 instead")

相关问题