猿问

C#将私有/公共RSA密钥从RSACryptoServiceProvider导出到PEM字符串

我有一个System.Security.Cryptography.RSACryptoServiceProvider的实例,我需要将它的密钥导出到PEM字符串-像这样:


-----BEGIN RSA PRIVATE KEY-----

MIICXAIBAAKBgQDUNPB6Lvx+tlP5QhSikADl71AjZf9KN31qrDpXNDNHEI0OTVJ1

OaP2l56bSKNo8trFne1NK/B4JzCuNP8x6oGCAG+7bFgkbTMzV2PCoDCRjNH957Q4

Gxgx1VoS6PjD3OigZnx5b9Hebbp3OrTuqNZaK/oLPGr5swxHILFVeHKupQIDAQAB

AoGAQk3MOZEGyZy0fjQ8eFKgRTfSBU1wR8Mwx6zKicbAotq0CBz2v7Pj3D+higlX

LYp7+rUOmUc6WoB8QGJEvlb0YZVxUg1yDLMWYPE7ddsHsOkBIs7zIyS6cqhn0yZD

VTRFjVST/EduvpUOL5hbyLSwuq+rbv0iPwGW5hkCHNEhx2ECQQDfLS5549wjiFXF

gcio8g715eMT+20we3YmgMJDcviMGwN/mArvnBgBQsFtCTsMoOxm68SfIrBYlKYy

BsFxn+19AkEA82q83pmcbGJRJ3ZMC/Pv+/+/XNFOvMkfT9qbuA6Lv69Z1yk7I1ie

FTH6tOmPUu4WsIOFtDuYbfV2pvpqx7GuSQJAK3SnvRIyNjUAxoF76fGgGh9WNPjb

DPqtSdf+e5Wycc18w+Z+EqPpRK2T7kBC4DWhcnTsBzSA8+6V4d3Q4ugKHQJATRhw

a3xxm65kD8CbA2omh0UQQgCVFJwKy8rsaRZKUtLh/JC1h1No9kOXKTeUSmrYSt3N

OjFp7OHCy84ihc8T6QJBANe+9xkN9hJYNK1pL1kSwXNuebzcgk3AMwHh7ThvjLgO

jruxbM2NyMM5tl9NZCgh1vKc2v5VaonqM1NBQPDeTTw=

-----END RSA PRIVATE KEY-----

但是根据MSDN文档,没有这种选择,只有某种XML导出。我不能使用BouncyCastle之类的任何第三方库。有什么方法可以产生这个字串吗?


侃侃无极
浏览 1819回答 3
3回答

ibeautiful

请注意:以下代码用于导出私钥。如果您要导出公共密钥,请参考我在此处给出的答案。PEM格式只是转换为Base64 的密钥(按PKCS#1)的ASN.1 DER编码。鉴于表示密钥所需的字段数量有限,创建快捷的DER编码器以输出适当的格式然后进行Base64编码非常简单。因此,下面的代码并不是特别优雅,但是可以做到:private static void ExportPrivateKey(RSACryptoServiceProvider csp, TextWriter outputStream){&nbsp; &nbsp; if (csp.PublicOnly) throw new ArgumentException("CSP does not contain a private key", "csp");&nbsp; &nbsp; var parameters = csp.ExportParameters(true);&nbsp; &nbsp; using (var stream = new MemoryStream())&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var writer = new BinaryWriter(stream);&nbsp; &nbsp; &nbsp; &nbsp; writer.Write((byte)0x30); // SEQUENCE&nbsp; &nbsp; &nbsp; &nbsp; using (var innerStream = new MemoryStream())&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var innerWriter = new BinaryWriter(innerStream);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, new byte[] { 0x00 }); // Version&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.Modulus);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.Exponent);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.D);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.P);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.Q);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.DP);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.DQ);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.InverseQ);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var length = (int)innerStream.Length;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeLength(writer, length);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.Write(innerStream.GetBuffer(), 0, length);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; var base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray();&nbsp; &nbsp; &nbsp; &nbsp; outputStream.WriteLine("-----BEGIN RSA PRIVATE KEY-----");&nbsp; &nbsp; &nbsp; &nbsp; // Output as Base64 with lines chopped at 64 characters&nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i < base64.Length; i += 64)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; outputStream.WriteLine(base64, i, Math.Min(64, base64.Length - i));&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; outputStream.WriteLine("-----END RSA PRIVATE KEY-----");&nbsp; &nbsp; }}private static void EncodeLength(BinaryWriter stream, int length){&nbsp; &nbsp; if (length < 0) throw new ArgumentOutOfRangeException("length", "Length must be non-negative");&nbsp; &nbsp; if (length < 0x80)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Short form&nbsp; &nbsp; &nbsp; &nbsp; stream.Write((byte)length);&nbsp; &nbsp; }&nbsp; &nbsp; else&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Long form&nbsp; &nbsp; &nbsp; &nbsp; var temp = length;&nbsp; &nbsp; &nbsp; &nbsp; var bytesRequired = 0;&nbsp; &nbsp; &nbsp; &nbsp; while (temp > 0)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; temp >>= 8;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bytesRequired++;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; stream.Write((byte)(bytesRequired | 0x80));&nbsp; &nbsp; &nbsp; &nbsp; for (var i = bytesRequired - 1; i >= 0; i--)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stream.Write((byte)(length >> (8 * i) & 0xff));&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}private static void EncodeIntegerBigEndian(BinaryWriter stream, byte[] value, bool forceUnsigned = true){&nbsp; &nbsp; stream.Write((byte)0x02); // INTEGER&nbsp; &nbsp; var prefixZeros = 0;&nbsp; &nbsp; for (var i = 0; i < value.Length; i++)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (value[i] != 0) break;&nbsp; &nbsp; &nbsp; &nbsp; prefixZeros++;&nbsp; &nbsp; }&nbsp; &nbsp; if (value.Length - prefixZeros == 0)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; EncodeLength(stream, 1);&nbsp; &nbsp; &nbsp; &nbsp; stream.Write((byte)0);&nbsp; &nbsp; }&nbsp; &nbsp; else&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (forceUnsigned && value[prefixZeros] > 0x7f)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Add a prefix zero to force unsigned if the MSB is 1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeLength(stream, value.Length - prefixZeros + 1);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stream.Write((byte)0);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeLength(stream, value.Length - prefixZeros);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; for (var i = prefixZeros; i < value.Length; i++)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stream.Write(value[i]);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}

GCT1015

要导出,请PublicKey使用以下代码:public static String ExportPublicKeyToPEMFormat(RSACryptoServiceProvider csp){&nbsp; &nbsp; TextWriter outputStream = new StringWriter();&nbsp; &nbsp; var parameters = csp.ExportParameters(false);&nbsp; &nbsp; using (var stream = new MemoryStream())&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var writer = new BinaryWriter(stream);&nbsp; &nbsp; &nbsp; &nbsp; writer.Write((byte)0x30); // SEQUENCE&nbsp; &nbsp; &nbsp; &nbsp; using (var innerStream = new MemoryStream())&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var innerWriter = new BinaryWriter(innerStream);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, new byte[] { 0x00 }); // Version&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.Modulus);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.Exponent);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //All Parameter Must Have Value so Set Other Parameter Value Whit Invalid Data&nbsp; (for keeping Key Structure&nbsp; use "parameters.Exponent" value for invalid data)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.D&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.P&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.Q&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.DP&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.DQ&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.InverseQ&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var length = (int)innerStream.Length;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeLength(writer, length);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.Write(innerStream.GetBuffer(), 0, length);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; var base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray();&nbsp; &nbsp; &nbsp; &nbsp; outputStream.WriteLine("-----BEGIN PUBLIC KEY-----");&nbsp; &nbsp; &nbsp; &nbsp; // Output as Base64 with lines chopped at 64 characters&nbsp; &nbsp; &nbsp; &nbsp; for (var i = 0; i < base64.Length; i += 64)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; outputStream.WriteLine(base64, i, Math.Min(64, base64.Length - i));&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; outputStream.WriteLine("-----END PUBLIC KEY-----");&nbsp; &nbsp; &nbsp; &nbsp; return outputStream.ToString();&nbsp; &nbsp; }}private static void EncodeIntegerBigEndian(BinaryWriter stream, byte[] value, bool forceUnsigned = true){&nbsp; &nbsp; stream.Write((byte)0x02); // INTEGER&nbsp; &nbsp; var prefixZeros = 0;&nbsp; &nbsp; for (var i = 0; i < value.Length; i++)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (value[i] != 0) break;&nbsp; &nbsp; &nbsp; &nbsp; prefixZeros++;&nbsp; &nbsp; }&nbsp; &nbsp; if (value.Length - prefixZeros == 0)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; EncodeLength(stream, 1);&nbsp; &nbsp; &nbsp; &nbsp; stream.Write((byte)0);&nbsp; &nbsp; }&nbsp; &nbsp; else&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (forceUnsigned && value[prefixZeros] > 0x7f)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Add a prefix zero to force unsigned if the MSB is 1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeLength(stream, value.Length - prefixZeros + 1);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stream.Write((byte)0);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EncodeLength(stream, value.Length - prefixZeros);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; for (var i = prefixZeros; i < value.Length; i++)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stream.Write(value[i]);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}private static void EncodeLength(BinaryWriter stream, int length){&nbsp; &nbsp; if (length < 0) throw new ArgumentOutOfRangeException("length", "Length must be non-negative");&nbsp; &nbsp; if (length < 0x80)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Short form&nbsp; &nbsp; &nbsp; &nbsp; stream.Write((byte)length);&nbsp; &nbsp; }&nbsp; &nbsp; else&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Long form&nbsp; &nbsp; &nbsp; &nbsp; var temp = length;&nbsp; &nbsp; &nbsp; &nbsp; var bytesRequired = 0;&nbsp; &nbsp; &nbsp; &nbsp; while (temp > 0)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; temp >>= 8;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bytesRequired++;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; stream.Write((byte)(bytesRequired | 0x80));&nbsp; &nbsp; &nbsp; &nbsp; for (var i = bytesRequired - 1; i >= 0; i--)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stream.Write((byte)(length >> (8 * i) & 0xff));&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}
随时随地看视频慕课网APP
我要回答