【发布时间】:2009-10-27 01:33:43
【问题描述】:
如何在 C# 中验证 DSA 签名?
给定:
- 消息文本,
- 签名摘要(通常为 ASN.1 DER 格式),
- 公钥(采用签名的 X.509 证书、PEM 或 DER 格式)
我尝试了很多方法,但都没有成功:
OpenSSL.NET: 库的各种奇怪错误;我有一个open thread running with the author over on SourceForge,但还没有解决这个问题。
Microsoft .NET API: 无法解压缩 DER 签名进行比较。 DSA 签名为 40 字节(两个 20 字节整数),但呈现为两个整数的 DER 编码序列,因此总长度范围为 46 到 48 字节(请参阅this post 以获得快速概述。)虽然.NET 包含解析 ASN.1/DER 的代码(因为它可以读取 DER 格式的证书),它被埋得很深,无法访问它,因此您可以正确地从 ASN.1/DER 编码中检索 40 个字节签名。这个问题让我想到了下一个选择……
BouncyCastle: 通过使用
Org.BouncyCastle.Asn1函数,我可以解析ASN.1 签名并将其拉入它的组件R 和S 整数值中。但是当我将这些传递给签名验证例程时,它失败了,没有给出任何解释。我不确定我是否做错了什么,因为 C# API 完全没有文档记录,而 Java 版本几乎没有文档记录(但我找不到任何示例或 HOWTO 信息。)
我已经为这个问题苦苦挣扎了大约一个星期。我知道以前一定有人做过,但我还没有找到任何完整/有效的例子。
我这里有三个 C# 项目,每个项目都完成了 95%,但有一个导致它失败的严重缺陷。任何有效的示例代码都将不胜感激。
编辑:这是我正在尝试验证的签名示例,已转换为 Base64 和 ASCII 十六进制以使其可发布。这个特定的是 47 字节,但正确的解析器仍然必须接受它,阅读 DER 规范以获取更多信息(BER/DER 添加前导 00 以确认 MSB 为 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 解析器确实不是一种选择,错误的空间太大,必须有一种方法来正确地做到这一点。
【问题讨论】:
-
我想知道您是否可以帮我一个忙,将标题从“验证 C# 中的 DSA 签名”更改为“使用 ASN.1 格式验证 C# 中的 DSA 签名”或类似的东西。可能有助于搜索人。
-
作为评论;我将采用另一种方式(验证在 .NET 中创建的 Java 签名);我必须编写一个从 .NET DSA 格式(仅 r||s 40 字节)到 DER 格式的转换器。根据我在此处找到的内容 (mombu.com/microsoft/security-crypto/…),DER 格式要求 r 和 s 为大端,但这根本不起作用,所以我将其保留为小端并且它可以工作......我还没有找到对此有什么非常清楚的;它应该是大端还是小端...如果有人知道,请插话!
-
我遇到了同样的问题,在这篇文章的帮助下,我决定手动进行 ASN.1-DER 解码;规范令人生畏,但实际上破译两个 20 字节整数的序列并不困难。一旦您确定 .NET 类期望签名以包含两个 20 字节整数连接的 40 字节数组的形式到达,这并不难。
标签: c# .net digital-signature asn.1