验证DSA签名在C#这是一个使用BER / DER EN codeD ASN.1格式这是一个、格式、BER、DSA

2023-09-04 01:48:52 作者:我家闺蜜最疯

我如何验证DSA签名在C#?

由于:

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

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

I've tried a number of approaches, but haven't had any success:

OpenSSL.NET :各种奇怪的错误与图书馆;我有与运行开线笔者在SourceForge上但一直没能解决这个呢。

OpenSSL.NET: various strange errors with the library; I've got an open thread running with the author over on SourceForge but haven't been able to resolve this yet.

微软.NET API:无法解开DER签名进行比较。一个DSA签名是40个字节(两个20字节的整数),但psented为两个整数的DER-CN codeD序列$ P $,所以总长度范围从46到48个字节(见的这个帖子用于快速浏览。)虽然.NET包含code解析ASN。 1 / DER(因为它可以读取DER格式的证书),它埋藏深,有没有办法来访问它,这样就可以正确地检索来自ASN.1 / DER EN codeD签名的40个字节。这个问题使我的下一个选项...

Microsoft .NET API: can't unpack the DER signature for comparison. A DSA signature is 40 bytes (two 20-byte integers), but is presented as an DER-encoded sequence of two integers, so the total length can range from 46 to 48 bytes (see this post for a quick overview.) While .NET includes code to parse ASN.1/DER (because it can read certificates in DER format), it's buried deep, and there's no way to access it so that you can correctly retrieve the 40 bytes from the ASN.1/DER encoded sig. This issue led me to the next option...

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

BouncyCastle: through the use of the Org.BouncyCastle.Asn1 functions, I can parse the ASN.1 signature and pull it into it's component R and S integer values. But when I pass these to the signature verification routines, it's failing with no explanation given. I'm not sure if I'm doing anything wrong, because the C# API is completely undocumented, and the Java version is barely documented (but there's no example or HOWTO information that I can find.)

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

I've been throwing myself at this problem for about a week now. I know someone must have done it before, but I haven't found any complete/working examples.

我有三C#项目坐在这里,每完成95%,但与导致它失败的一个关键缺陷。任何工作的例子code会大大AP preciated。

I've got three C# projects sitting here, each 95% complete but with one critical flaw that causes it to fail. Any working example code would be tremendously appreciated.

编辑:这是我想要验证签名的例子,转化为Base64和十六进制ASCII码,使之过帐。这种特殊的一个是47个字节,但是一个适当的解析器仍必须接受它,阅读了关于该DER规范的更多信息(BER / DER增加了导致00来确认的标志,如果最高位为1)

edit: here's an example of a signature I'm trying to verify, converted to Base64 and ASCII hex to make it postable. This particular one is 47 bytes but a proper parser must still accept it, read up on the DER spec for more info (BER/DER adds a leading 00 to confirm the sign if the MSB is 1)

Base64: MC0CFQCUgq2DEHWzp3O4nOdo38mDu8mStwIUadZmbin7BvXxpeoJh7dhquD2CTM=

ASCII Hex: 302d0215009482ad831075b3a773b89ce768dfc983bbc992b7021469d6666e29fb06f5f1a5ea0987b761aae0f60933

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

Structure is per the DER spec; it parses as follows:

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解析器真的不是一种选择,太多的闪失而且也必须是一个办法做到这一点正确。

Writing my own DER parser is really not an option, too much room for error and there's got to be a way to do this properly.

推荐答案

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

Using BouncyCastle (v1.7), I can do this (don't forget error checking, of course):

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!
}

我的signature.bin使用OpenSSL的产生,例如: OpenSSL的DGST -sha1 -sign private.key data.bin> signature.bin

 
精彩推荐
图片推荐