日期:2014-05-16  浏览次数:21250 次

X509Certificate2类怎样导入一个公钥字符串
请教各位.net的X509Certificate2类


需求概述:通过16进制的字符串,得到公钥,并进行验签

需求详述:

A单位有一个cer的公钥证书,这个cer公钥证书文件不能以文件形式拿出。只能通过X509Certificate2.GetPublicKeyString()方法得到这个公钥证书的16进制字符串,如“G6DYE3YDFUYGUFGUFYSFUAGFSYUAFFUAYGFU6GFSYFGFSDFFASF”

然后通过互联网浏览器把这串公钥字符串提交B单位服务器(只能拿到这串字符串,无公钥的其它信息)。B公司要使用这个串字符串得到公钥,并使用公钥进行验签(已有明文和私钥签名后的密文及算法)。

现在关键问题是:RSACryptoServiceProvider和X509Certificate2这2个类,好像未提供方法从一串16进制的公钥字符串得到公钥并加载到RSA里面去。

B单位尝试把16进制字符串转成byte[]数组,但RSACryptoServiceProvider和X509Certificate2这2个类,好像也没有从byte[]数组得到公钥并加载到RSA里面去的方法。

------解决方案--------------------
以及 http://msdn.microsoft.com/zh-cn/library/system.security.cryptography.rsa.exportparameters(v=vs.100).aspx
------解决方案--------------------
使用X509Certificate2.GetPublicKeyString()难度比较大。

它格式用的是DER Encoding of ASN.1 Types。
比如3082010A0282010100D93E8921F06B5A2E9...0203010001
30:表示SEQUENCE类型
82010A:表示SEQUENCE长度为010A(其中82超过80,表示后面有2个字节的长度信息)
02:表示整数类型
820101:表示整数长度为0101(十进制为257)
00D93E89...:该整数就是modulus,00用来表示正整数,扣除00后还有256个字节,因此modulus为256个字节
最后是Exponent
0203010001: 02表示整数,03长度为3,010001就是Exponent

既然A单位可以得到GetPublicKeyString,建议A单位转为提交
X509Certificate2.PublicKey.Key.ToXmlString()
,给出的xml类似:
<RSAKeyValue>
  <Modulus>2T6J...Yvy3PTw==</Modulus>
  <Exponent>AQAB</Exponent>
</RSAKeyValue>

该xml直接给出了Modulus和Exponent,并可以直接被RSACryptoServiceProvider导入。
如果注意观察,其中Exponent的AQAB就是010001这3个字节的Base64编码,而Modulus的2T6J...就是D93E89...的Base64编码。


DER Encoding of ASN.1 Types可参考
http://msdn.microsoft.com/en-us/library/windows/desktop/bb648640%28v=vs.85%29.aspx
http://en.wikipedia.org/wiki/Distinguished_Encoding_Rules#DER_encoding