如何在C#中使用System.Formats.Asn1.AsnReader读取公钥的指数和模数
如何在C#中使用System.Formats.Asn1.AsnReader读取公钥的指数和模数
嘿,看得出来你已经在使用System.Formats.Asn1.AsnReader解析DER证书的路上走了一大段啦!既然已经成功初始化了读取器、读到了tsb部分,甚至摸到了公钥信息里的算法环节,那接下来拿到RSA公钥的指数和模数其实就差最后几步,我来给你详细说说:
首先先回顾下你已经完成的关键操作:
- 成功初始化了AsnReader:
AsnReader readerAll = new AsnReader(new ReadOnlyMemory<byte>(certificateDER), AsnEncodingRules.DER); - 顺利读取到了tsb区域的内容,并且进到了公钥信息(SubjectPublicKeyInfo)的算法部分
接下来的核心逻辑是:公钥信息里的公钥内容是以BIT STRING的形式存储的,里面包裹着一个RSA公钥的SEQUENCE结构,这个SEQUENCE就包含了我们要的模数(n)和指数(e)。具体步骤如下:
读取公钥的BIT STRING
在你处理完公钥信息里的算法标识符之后,接下来要读取的就是公钥的BIT STRING数据,这个数据里就是我们需要解析的RSA公钥内容:// 读取BIT STRING,unusedBits一般为0(因为公钥内容是整字节的) ReadOnlyMemory<byte> publicKeyBitString = readerAll.ReadBitString(out int unusedBits);创建新的AsnReader解析公钥内容
因为BIT STRING里的内容是一个独立的ASN.1 SEQUENCE,所以我们需要用这个内容创建一个新的AsnReader来单独解析:AsnReader publicKeyReader = new AsnReader(publicKeyBitString, AsnEncodingRules.DER);读取模数和指数
RSA公钥的SEQUENCE里包含两个INTEGER类型的元素,第一个是模数(n),第二个是指数(e),我们可以依次读取它们:// 读取公钥的SEQUENCE,用using确保资源正确释放 using (AsnReader rsaPublicKeyReader = publicKeyReader.ReadSequence()) { // 读取模数(n),转换为BigInteger方便后续使用 ReadOnlyMemory<byte> modulusBytes = rsaPublicKeyReader.ReadIntegerBytes(); BigInteger modulus = new BigInteger(modulusBytes.Span, isUnsigned: true, isBigEndian: true); // 读取指数(e),同样转换为BigInteger ReadOnlyMemory<byte> exponentBytes = rsaPublicKeyReader.ReadIntegerBytes(); BigInteger exponent = new BigInteger(exponentBytes.Span, isUnsigned: true, isBigEndian: true); // 到这里你就成功拿到了模数和指数,可以根据业务需求使用啦 }
一些小提醒:
- 全程要保持编码规则为
AsnEncodingRules.DER,因为X.509证书的ASN.1编码都是遵循DER规范的 - 如果你的公钥不是RSA类型(比如ECDSA),那公钥的结构会不一样,但从你提到的“指数和模数”来看,应该是RSA公钥没问题
- 读取整数的时候,
ReadIntegerBytes返回的是原始的大端字节序无符号整数,用BigInteger的对应构造方法可以正确解析
备注:内容来源于stack exchange,提问作者Tamil Shenbaga Selvi




