二、PEM私钥的使用
PEM私钥文件格式
使用NotePad打开一个PEM格式的私钥,如下图一:
-----BEGIN RSA PRIVATE KEY-----
MIIEpgIBAAKCAQEA0eU3Gfy/ybCZbImniKFW6EZ11YWmt1UYt4dRcxZzPlvceiNW
V2TWjPFsQTHYeEWVDIGhh+oPVJCS6ZCErgBOW2VlLZuR+H87d4oqcjK+eVt/weOH
C/kPKos6s0hjzPyJT7p/jsYXMVa56vQQAhdDLmR0B2lyzkeAFHdsBHvorq6xjSeY
a4h194nY+L9pTEmZoCSUiD+G+A9F/p/QYbITa7uYqiqMLRAB84OrWNvfjKNbm740
x3l5ZNc3hicb+VP4Nq2Gvkb7jBLmoGBH1CZ4xZ10wXXZBdPsyZmDoUPh+Z6SYU7F
KiRFmkva4YPrvlgJQSLkWtNbRI61DUsYir7NFQIDAQABAoIBAQDQU3fwRCu7LJvq
3Wm6M6CFpEGaLzA8sKp6pkVSPEsf7p8TXvV4gm5sr8Zpouae4TlBk3xW4RpcLa6T
… …
N5U1B4DhqSmZJw7BI9Ra3LHb5GIqimIqcWOw1N6CpX0skfc04e0CQ164
-----END RSA PRIVATE KEY-----
与公钥格式一致,首行和末行是标识,中间部分是用Base64编码的数据区,这部分数据可以用Pad++等工具解码,就不占用篇幅展示了。这个数据区中储存了私钥中需要使用的各种参数,如Modulus、Exponent、D、P、DP、DQ、InverseQ等。与前一篇公钥存储格式类似(RSA算法中PEM与XML密钥相互转换—C#实现(一))私钥中各项参数存储格式详细总结见下表:
各块按顺序依次排列,注意长度的解算方式与前篇相同。代码如下:
private static RSAParameters GetRSAParametersPrivate(byte[] keyBytes)
{
RSAParameters p;
//get innerParam
if (keyBytes[0] != 0x30) throw new Exception($"sequence wrong {keyBytes[0]:x2}");
int len = 0;
int id = 1;
len = DecodeLenth(keyBytes, ref id);
int inner0 = id + 1;
int inner1 = inner0 + len - 1;
id = inner0;
var version = DecodeIntegerBigEndian(keyBytes, ref id);
p.Modulus = DecodeIntegerBigEndian(keyBytes, ref id);
p.Exponent = DecodeIntegerBigEndian(keyBytes, ref id);
p.D = DecodeIntegerBigEndian(keyBytes, ref id);
p.P = DecodeIntegerBigEndian(keyBytes, ref id);
p.Q = DecodeIntegerBigEndian(keyBytes, ref id);
p.DP = DecodeIntegerBigEndian(keyBytes, ref id);
p.DQ = DecodeIntegerBigEndian(keyBytes, ref id);
p.InverseQ = DecodeIntegerBigEndian(keyBytes, ref id);
return p;
}
这个方法传入参数是私钥的数据部分按Base64解码后得到的字节数组,可以使用:
Convert.FromBase64String(s)方法得到。
另外方法调用了2个子方法:DecodeLenth、DecodeIntegerBigEndian,在前一篇相同。
至此,介绍了在DotNet中直接使用PEM格式公钥、私钥的方法,和代码。
上述代码在VS2017,dotNet4.6,RSA2048的环境下运行成功。
三、PEM格式密钥转换为XML格式
DotNet中使用的密钥是XML格式,通过前篇和本篇的介绍,要实现PEM格式转换XML格式也就水到渠成了。方法:
- 通成上面的方法,读取PEM密钥,返回RSAParameters。
- 利用ImportParameters方法,生成RSA实例。
- 利用ToXmlString(false)生成XML公钥,ToXmlString(true)生成私钥。