/// <summary>
/// parsing pem file private key
/// </summary>
/// <param name="pemstr">pkcs8 private key</param>
/// <returns></returns>
public static RSACryptoServiceProvider DecodePemPrivateKey(String pemstr)
{
byte[] pkcs8privatekey;
pkcs8privatekey = Convert.FromBase64String(pemstr);
if (pkcs8privatekey != null)
{
RSACryptoServiceProvider rsa = DecodePrivateKeyInfo(pkcs8privatekey);
return rsa;
}
else
return null;
}
/// <summary>
/// 打印出XML格式的私钥
/// </summary>
/// <param name="pkcs8"></param>
/// <returns></returns>
private static RSACryptoServiceProvider DecodePrivateKeyInfo(byte[] pkcs8)
{
byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
byte[] seq = new byte[15];
MemoryStream mem = new MemoryStream(pkcs8);
int lenstream = (int)mem.Length;
BinaryReader binr = new BinaryReader(mem);
byte bt = 0;
ushort twobytes = 0;
try
{
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130)
binr.ReadByte();
else if (twobytes == 0x8230)
binr.ReadInt16();
else
return null;
bt = binr.ReadByte();
if (bt != 0x02)
return null;
twobytes = binr.ReadUInt16();
if (twobytes != 0x0001)
return null;
seq = binr.ReadBytes(15);
if (!CompareBytearrays(seq, SeqOID))
return null;
bt = binr.ReadByte();
if (bt != 0x04)
return null;
bt = binr.ReadByte();
if (bt == 0x81)
binr.ReadByte();
else
if (bt == 0x82)
binr.ReadUInt16();
byte[] rsaprivkey = binr.ReadBytes((int)(lenstream - mem.Position));
RSACryptoServiceProvider rsacsp = DecodeRSAPrivateKey(rsaprivkey);
Console.WriteLine(rsacsp.ToXmlString(true));
return rsacsp;
}
catch (Exception)
{
return null;
}
finally { binr.Close(); }
}
private static bool CompareBytearrays(byte[] a, byte[] b)
{
if (a.Length != b.Length)
return false;
int i = 0;
foreach (byte c in a)
{
if (c != b[i])
return false;
i++;
}
return true;
}
private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
{
byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
MemoryStream mem = new MemoryStream(privkey);
BinaryReader binr = new BinaryReader(mem);
byte bt = 0;
ushort twobytes = 0;
int elems = 0;
try
{
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130)
binr.ReadByte();
else if (twobytes == 0x8230)
binr.ReadInt16();
else
return null;
twobytes = binr.ReadUInt16();
if (twobytes != 0x0102)
return null;
bt = binr.ReadByte();
if (bt != 0x00)
return null;
elems = GetIntegerSize(binr);
MODULUS = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
E = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
D = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
P = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
Q = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
DP = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
DQ = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
IQ = binr.ReadBytes(elems);
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
RSAParameters RSAparams = new RSAParameters();
RSAparams.Modulus = MODULUS;
RSAparams.Exponent = E;
RSAparams.D = D;
RSAparams.P = P;
RSAparams.Q = Q;
RSAparams.DP = DP;
RSAparams.DQ = DQ;
RSAparams.InverseQ = IQ;
RSA.ImportParameters(RSAparams);
return RSA;
}
catch (Exception)
{
return null;
}
finally { binr.Close(); }
}
private static int GetIntegerSize(BinaryReader binr)
{
byte bt = 0;
byte lowbyte = 0x00;
byte highbyte = 0x00;
int count = 0;
bt = binr.ReadByte();
if (bt != 0x02)
return 0;
bt = binr.ReadByte();
if (bt == 0x81)
count = binr.ReadByte();
else
if (bt == 0x82)
{
highbyte = binr.ReadByte();
lowbyte = binr.ReadByte();
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
count = BitConverter.ToInt32(modint, 0);
}
else
{
count = bt;
}
while (binr.ReadByte() == 0x00)
{
count -= 1;
}
binr.BaseStream.Seek(-1, SeekOrigin.Current);
return count;
}
通过将pkcs8密钥生成XML格式的密钥然后通过FromXmlString方法导入再进行解密。
public static String decryptByPrivateKey(String inputStr, string privateKey, Encoding encoding)
{
String result = null;
byte[] input = Convert.FromBase64String(inputStr);
RSAParameters rasParams = ConvertFromPrivateKey(privateKey);
RSACryptoServiceProvider rsaService = new RSACryptoServiceProvider();
//rsaService.ImportParameters(rasParams);
rsaService.FromXmlString(@"<RSAKeyValue><Modulus>pEDZ+Bd97XPLbRdYZqkSHWgwU5vgGtUXIiTO+VOwjKL6UQFmGb2Uk6D5fttCYuwDNT59ECrHtqbKWF5G4MtQD03Ss8WLobxwpjR8XiQ8JbIgc1IQoUPFxS8Ls7LTOzMH2DTDPHLySSGKtrHrNnxmhDofhseRsue9LQAVlt6Qj3M=</Modulus><Exponent>AQAB</Exponent><P>0IcsAdPe2QcGnXjDc1ABJGOYpUEJnBGzmAC0dRRCBGJFSwUBkyTG6VNboPtcKk504lsoZyF8oUlxMUJuYznJrw==</P><Q>yaVjzQquigXHbBfXu9xbdILDDacuybb0IEk0tH/AV6MouHRm6nCtdeF9L0ZGdEdoJreeRHmH95+jjRRxti57fQ==</Q><DP>a6Q7HT5nHJS533PFQLMdw9D9rOBju4KPuHk0rfMlGOo5Zr5Qz8n+O9dhxzm5m8UgJPB1bLcmhINKwOjP3ryn1Q==</DP><DQ>grpu0WezcFf+yd1LR8e8ovSDcD6K3st1ydisCrkoAakNpUgR0LvsORhPCG8PDiOdKjywpsQDmk4swjIW5n2MIQ==</DQ><InverseQ>lKFa6ityR0OLoOu9qhTTdZfFO3hr+ZETelUBd6hMlTPVHu6AHH1eeQ0Q6ELG8UGkgJH3UlEG/9btzoFpw2LQzQ==</InverseQ><D>h0p3fzbyXYycSX4KLX0jU5+G9scUn2VXiaMh7BH4AM8ZOXHahGc4IyVbfBbjppFZzxhqcM+b8qGNV55H6U7t4GtR9JtxUqqSZ/JqgQnTd8PUqrJI2Z/HpeY0lzvXHF1VOtzgP7sBPKnZikoeoJH7FEt9ghtGY6rAXj6A9RCOMCk=</D></RSAKeyValue>");
/*
rsaService.FromXmlString(@"<RSAKeyValue>
<Modulus>4hH5e3UWRo9TSzHcM/DPvTzHhRKaV/28TUCFBx5jg/ErfSJiMQh3plp6h9BkupMrO0gNq198hzMpy/0rt9w3KC7Mm4ZYLNqv8GoynQE1XZnDdJu3JXu5wwAvDg7PYsXhtGikG6kzERsNAQ4enyOCGuWyRj28WsitrKEpIlhAtDE=</Modulus>
<Exponent>AQAB</Exponent>
<P>+plx7dXt1GKvoE+4G4aeLKohyp6eglOU1NhvfYlJYFtKL8HdtYqb1dt4El+LZ8s+teP9O1+wEDS/LFHV8e8lFw==</P>
<Q>5vEzwxHIEwZU2mbrqWSp8tP1oH/Xb53Kvlhanub+wjR1kuobKCeBiffgAF92blMJKl1RFxRuwFiT4w//2ARN9w==</Q>
<DP>0WTwDqRn8sR3LcQO+WkVuAp869p4ZjvCq8sh9cqGNm5xYdBjGnN0XVDiVq/hQ1xPzRpxGXCOJCx+5WCIHX0PBw==</DP>
<DQ>eTL4sVUxpRpbicsdvmZ/8lpeu/6bt44eCssfs+kSpiUV1yZZXjdtelTGECwJYVjepIcYuX4VqYhTBIUvBdUsfQ==</DQ>
<InverseQ>ti+ID24mDqOdPQOCR5RYCKadoTYm844R9XtRzQdTXgnnXHOURcl/+Ovr1X+PFLb2Aw/yV+qSaIky3reyhdfhRw==</InverseQ>
<D>Ph9EWDmXknImKF6eLSO6Yj0Gcrnm8dEG4o+dPpSKMiKembdOFj1Ga88nJpUMaPyx/4tQPkxx8tELZkO+tLpt6TeHrZ8mVXmKfqEDhzya+wXrc60799i72R6FTHSYz8AbcEf/RMh5OgCz2oyg/J/ck4tGPMpJwjjv4s0dYBsmfYU=</D>
</RSAKeyValue>");
*/
RSAParameters rsapars = rsaService.ExportParameters(false);
byte[] output = rsaService.Decrypt(input, false);
result = encoding.GetString(output);
return result;
}