C# – 如何计算特定哈希算法的ASN.1 DER编码?

给定一个像SHA1或SHA256这样的哈希算法,我将如何获得RFC3447中定义的ASN.1 DER编码? (参见第42页 – 链接 )以下是所需的输出。

MD5 30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04 10 SHA-1 30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 SHA-256 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 SHA-384 30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30 SHA-512 30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40 

我希望有一些聪明的方法可以在C#中执行此操作,不需要我将Oid写入ASN.1 DER转换例程(或硬编码)。 有任何想法吗?

这将使你成为一部分:

 string oidString = CryptoConfig.MapNameToOID(hashName); // fx "MD5" byte[] encodedOid = CryptoConfig.EncodeOID(oidString); // Gives you fx 06 08 2a 86 48 86 f7 0d 02 05 

然后你只需要在SEQUENCE标题中插入它( 3030050004 )。

当然,如果你想创建一个RSA PKCS#1 v1.5签名,你最好只使用RSAPKCS1SignatureFormatter


编辑:更多细节:

您要编码的ASN.1是这样的:

 DigestInfo ::= SEQUENCE { digestAlgorithm AlgorithmIdentifier, digest OCTET STRING } 

哪里

 AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameters ANY DEFINED BY algorithm OPTIONAL } 

所以从内部开始:digest-AlgorithmIdentifier包括SEQUENCE -tag(30),长度(我们将回到那里),OID和一些参数。 fx SHA-1的OID是1.3.14.3.2.26,其编码为06 05 2b 0e 03 02 1a (OID-tag 06,长度5和OID的编码)。 所有常用的散列函数都有NULL作为参数,编码为05 00 。 所以AlgorithmIdentifier包含9个字节 – 这就是上面的内容。

我们现在可以继续使用DigestInfo的其余部分:一个OCTET STRING,它包含哈希的值。 SHA-1的20字节散列将被编码为04 20

DigestInfo的内容长度现在是11 + 22字节()。 我们需要使用SEQUENCE -tag启动DigestInfo,因此我们最终得到: 30 21 30 09 06 05 2b 0w 02 01 1a 05 00 04 20

如果您需要自己生成它,您现在应该能够看到length2 = encodedOid.Length + 2并且该length = length2 + 2 + 2 + hashlength。

如果您需要有关编码ASN.1的更多信息,我可以推荐Burt Kaliski的ASA.1 ,BER和DER子集的A Layman指南 。