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

Tay*_*ese 8 .net c# cryptography

给定一个哈希算法,如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
Run Code Online (Sandbox Code Playgroud)

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

Ras*_*ber 16

这将使你成为一部分:

string oidString = CryptoConfig.MapNameToOID(hashName); // f.x. "MD5"
byte[] encodedOid = CryptoConfig.EncodeOID(oidString); // Gives you f.x. 06 08 2a 86 48 86 f7 0d 02 05
Run Code Online (Sandbox Code Playgroud)

然后你只需要在SEQUENCE-heading(30<length>30<length2><oid>050004<hashlength>)中插入它.

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


编辑:更多细节:

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

DigestInfo ::= SEQUENCE {
      digestAlgorithm AlgorithmIdentifier,
      digest OCTET STRING
}
Run Code Online (Sandbox Code Playgroud)

哪里

AlgorithmIdentifier  ::=  SEQUENCE  {
      algorithm               OBJECT IDENTIFIER,
      parameters              ANY DEFINED BY algorithm OPTIONAL  
}
Run Code Online (Sandbox Code Playgroud)

所以从内部开始: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 <HASH>.

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

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

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