验证在C#DSA签名是一个使用BER / DER ASN.1编码格式(Verify a DSA si

2019-09-01 09:24发布

我如何可以验证在C#中的DSA签名?

鉴于:

  • 消息文本,
  • 一个签名的摘要(通常ASN.1 DER格式),
  • 公钥(在签名的X.509证书,PEM或DER格式)

我已经尝试了许多方法,但都没有成功:

  • OpenSSL.NET :与库各种奇怪的错误; 我有一个与作者在SourceForge上运行的开放线程 ,但一直没能还没有解决这个问题。

  • 微软.NET API:无法解开DER签名进行比较。 一个DSA签名是40个字节(2 20字节的整数),但表示为两个整数的DER编码序列,所以总长度可以从46至48个字节(参照范围此篇用于快速概览。)虽然。 NET包括代码来解析ASN.1 / DER(因为它可以读取DER格式的证书),它深埋,并没有办法访问它,这样就可以正确地检索来自ASN.1 / DER编码SIG的40个字节。 这个问题使我的下一个选项...

  • BouncyCastle的:通过使用的Org.BouncyCastle.Asn1功能,我可以解析ASN.1签名和拉入它的分量R和S的整数值。 但是,当我通过这些来签名验证程序,它的失败,没有给出解释。 我不知道如果我做错什么,因为C#API 完全无证和Java版本几乎没有记录(但没有,我可以找到例子或HOWTO信息。)

现在我已经抛出自己在这个问题一个星期左右。 我知道一定有人这么做过,但我还没有发现任何完整的/工作的例子。

我有三个C#项目坐在这里,每完成95%,但与导致它失败的一个严重的安全漏洞。 任何工作示例代码将被极大地理解。

编辑:这里有一个签名我试图验证的一个例子,转换为Base64和ASCII十六进制,使其可发布。 这种特殊的一个是47个字节,但是一个适当的解析器仍必须接受它,对于DER规格读了更多的信息(BER / DER增加了00领先确认符号,如果最高位为1)

Base64: MC0CFQCUgq2DEHWzp3O4nOdo38mDu8mStwIUadZmbin7BvXxpeoJh7dhquD2CTM=

ASCII Hex: 302d0215009482ad831075b3a773b89ce768dfc983bbc992b7021469d6666e29fb06f5f1a5ea0987b761aae0f60933

结构是每DER规范; 它解析如下:

30 2d: sequence, length 45 (may vary from 44 to 46)
 02 15: integer, length 21 (first byte is 00 to confirm sign)
  009482ad831075b3a773b89ce768dfc983bbc992b7
 02 14: integer, length 20 (leading 00 not necessary for this one)
  69d6666e29fb06f5f1a5ea0987b761aae0f60933

写我自己的DER解析器真的不是一个选择,太多的闪失和我们有了一个方法可以正确地做到这一点。

Answer 1:

看看这个: http://www.codeproject.com/KB/security/CryptoInteropSign.aspx我有,似乎非常相似,你的这解决了这个问题。



Answer 2:

一段代码,用于验证DSA签名可以在找到NSsh项目。 它不适合您的需要,因为公共密钥不是从X.509证书中提取,但是它可能会给你一个起点。



Answer 3:

另一个很好的例子是DotNetAutoUpdate代码。 它采用RSA,但它应该是相当简单的切换到DSA。 特别是看看这个文件:

http://code.google.com/p/dotnetautoupdate/source/browse/trunk/source/DotNetAutoUpdate/UpdateKeys.cs


编辑:基本上你想类似这样:

var sha1 = new SHA1Managed();
var hash = sha1.ComputeHash(inputStream);

var signatureFormatter = new DSASignatureDeformatter(dsa);
signatureFormatter.SetHashAlgorithm("SHA1");
bool valid = signatureFormatter.VerifySignature(hash, signature); 

有关详细信息MSDN 。


编辑:另一种选择是Mono.Security库:

  • 还有一类是用于读取ASN1
  • 此外,还有一个组装阅读X.509 cerficiates。

我不知道是否有帮助?



Answer 4:

使用BouncyCastle的(V1.7),我可以做到这一点(不要忘了错误检查,当然):

using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Org.BouncyCastle.Asn1;

byte[] signature = ReadFile("signature.bin");
byte[] dataToVerify = ReadFile("data.bin");
byte[] rawPublicKey = KeyResources.publickey; // My public key is in a resource

var x509 = new X509Certificate2(rawPublicKey);
var dsa = x509.PublicKey.Key as DSACryptoServiceProvider;

// extract signature components from ASN1 formatted signature
DSASignatureDeformatter DSADeformatter = new DSASignatureDeformatter(dsa);
DSADeformatter.SetHashAlgorithm("SHA1");

Asn1InputStream bIn = new Asn1InputStream(new MemoryStream(signature));
DerSequence seq = bIn.ReadObject() as DerSequence;

var r11 = seq[0].GetEncoded();
var r21 = seq[1].GetEncoded();

byte[] p1363 = new byte[40];
Array.Copy(r11, r11.Length - 20, p1363, 0, 20);
Array.Copy(r21, r21.Length - 20, p1363, 20, 20);

// and finally we can verify
if (!DSADeformatter.VerifySignature(new SHA1CryptoServiceProvider().ComputeHash(dataToVerify), p1363))
{
    // Noo, mismatch!
}

使用OpenSSL生成我signature.bin,如openssl dgst -sha1 -sign private.key data.bin > signature.bin



Answer 5:

JFYI:有时我看到有效45字节DER DSA签名(整数中的一个是19个字节不是20)中,由OpenSSL的命令行工具生成的。 它似乎可以有44个字节(均为19个字节),所以你最好在6到48个字节,而不是从46到48 ;-)期待什么



文章来源: Verify a DSA signature in C# that's using BER/DER encoded ASN.1 format