使用 .NET 的 OpenSSL S/MIME 签名
对于我正在开发的应用程序,我需要先创建签名文件,然后才能上传文件。它的文档解释了如何使用 openssl 执行此操作:
首先,您需要准备密钥:
$ openssl pkcs12 -in certificate.pfx -passin pass:xxxxxxxxxx -out pem -clcerts -nokeys
$ openssl pkcs12 -in certificate.pfx -passin pass:xxxxxxxxxx -passout pass:xxxxxx -out key
之后您可以使用以下语法对任何文件进行签名:
$ openssl smime -sign -in inputfile -signer pem -inkey key -passin pass:xxxxxx -outform PEM -out signaturefile
这可行,但我宁愿避免运行外部程序来创建签名文件(如果可以使用本机 .NET 代码实现的话)。
我尝试在 vb.net 中对此进行编码并得到以下结果:
Public Shared Sub SignFile(ByVal theFilename As String, ByVal theCertFile As String, ByVal thePassword As String, ByVal theDestination As String)
Dim aCertificate = New X509Certificates.X509Certificate2(theCertFile, thePassword)
Dim aByteArray = IO.File.ReadAllBytes(theFilename)
Dim anOid = New System.Security.Cryptography.Oid("1.2.840.113549.1.7.2")
Dim aContentInfo = New Pkcs.ContentInfo(anOid, aByteArray)
Dim aSignedCms = New Pkcs.SignedCms(aContentInfo, True)
Dim aCmsSigner = New Pkcs.CmsSigner(Pkcs.SubjectIdentifierType.IssuerAndSerialNumber, aCertificate)
aSignedCms.ComputeSignature(aCmsSigner)
Dim aSignature = Convert.ToBase64String(aSignedCms.Encode())
IO.File.WriteAllText(theDestination, Convert.ToBase64String(anOutput.ToArray()))
End Sub
它生成的文件并不完全是 openssl 所期望的:我仍然需要插入 -----BEGIN PKCS7-----< /code> 和
-----END PKCS7-----
并添加换行符,以使行长度不超过 65 个字符。 但是,即使这样做之后,我以这种方式创建的签名也是无效的,当我检查 openssl 时,我收到以下错误:
5768:error:21071065:PKCS7 routines:PKCS7_signatureVerify:digest failure:.\crypto\pkcs7\pk7_doit.c:1051:
5768:error:21075069:PKCS7 routines:PKCS7_verify:signature failure:.\crypto\pkcs7\pk7_smime.c:410:
我想我在某处忘记了一个小细节,但我无法弄清楚是什么。
任何人都可以帮我使该代码工作吗?如果没有,请指出具有此类功能的 .NET 库,并可能提供一个如何实现该功能的示例?
For an application I'm developing I need to create a signature file before I can upload files. The documentation of it explains how to do this with openssl:
First you need to prepare your key:
$ openssl pkcs12 -in certificate.pfx -passin pass:xxxxxxxxxx -out pem -clcerts -nokeys
$ openssl pkcs12 -in certificate.pfx -passin pass:xxxxxxxxxx -passout pass:xxxxxx -out key
After which you can sign any file using the following syntax:
$ openssl smime -sign -in inputfile -signer pem -inkey key -passin pass:xxxxxx -outform PEM -out signaturefile
This works, but I'd rather avoid having to run an external program just to create signature files if it's possible to do it with native .NET code.
I've tried to code this in vb.net and got the following:
Public Shared Sub SignFile(ByVal theFilename As String, ByVal theCertFile As String, ByVal thePassword As String, ByVal theDestination As String)
Dim aCertificate = New X509Certificates.X509Certificate2(theCertFile, thePassword)
Dim aByteArray = IO.File.ReadAllBytes(theFilename)
Dim anOid = New System.Security.Cryptography.Oid("1.2.840.113549.1.7.2")
Dim aContentInfo = New Pkcs.ContentInfo(anOid, aByteArray)
Dim aSignedCms = New Pkcs.SignedCms(aContentInfo, True)
Dim aCmsSigner = New Pkcs.CmsSigner(Pkcs.SubjectIdentifierType.IssuerAndSerialNumber, aCertificate)
aSignedCms.ComputeSignature(aCmsSigner)
Dim aSignature = Convert.ToBase64String(aSignedCms.Encode())
IO.File.WriteAllText(theDestination, Convert.ToBase64String(anOutput.ToArray()))
End Sub
The file it makes isn't exactly what openssl expects: I still need to insert the -----BEGIN PKCS7-----
and -----END PKCS7-----
and add in line breaks so that lines aren't longer than 65 characters.
But, even after doing that, the signature I made this way isn't valid, when I check with openssl I get the following error:
5768:error:21071065:PKCS7 routines:PKCS7_signatureVerify:digest failure:.\crypto\pkcs7\pk7_doit.c:1051:
5768:error:21075069:PKCS7 routines:PKCS7_verify:signature failure:.\crypto\pkcs7\pk7_smime.c:410:
I think I'm forgetting a small detail somewhere, but I can't just figure out what.
Can anyone help me out make that code work? And if not, point to a .NET library that has such functionality with possibly an example of how to do it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您具体添加了哪些换行符? CRLF 还是只是 LF?
我在验证 smime 消息时遇到类似的问题。我找到了原因。 OpenSSL 将换行符更改为 CRLF(我的消息仅使用 LF),因此内容变得与原始内容不同,并且摘要检查失败。也许你也是这种情况?
不幸的是我找不到解决方案。
What exact line breaks do you add? CRLF or just LF?
I have similar problem verifying smime message. And I find the cause. OpenSSL changes line breaks to CRLF (my message use only LF) so content become different from original and digest check fails. May be it is you case too?
Unfortunately I can't find solution.