How to read a PEM RSA private key from .NET
Update 03/03/2021
.NET 5 now supports this out of the box.
To try the code snippet below, generate a keypair and encrypt some text at http://travistidwell.com/jsencrypt/demo/
var privateKey = @"-----BEGIN RSA PRIVATE KEY-----
{ the full PEM private key }
-----END RSA PRIVATE KEY-----";
var rsa = RSA.Create();
rsa.ImportFromPem(privateKey.ToCharArray());
var decryptedBytes = rsa.Decrypt(
Convert.FromBase64String("{ base64-encoded encrypted string }"),
RSAEncryptionPadding.Pkcs1
);
// this will print the original unencrypted string
Console.WriteLine(Encoding.UTF8.GetString(decryptedBytes));
Original answer
I solved, thanks. In case anyone's interested, bouncycastle did the trick, just took me some time due to lack of knowledge from on my side and documentation. This is the code:
var bytesToDecrypt = Convert.FromBase64String("la0Cz.....D43g=="); // string to decrypt, base64 encoded
AsymmetricCipherKeyPair keyPair;
using (var reader = File.OpenText(@"c:\myprivatekey.pem")) // file containing RSA PKCS1 private key
keyPair = (AsymmetricCipherKeyPair) new PemReader(reader).ReadObject();
var decryptEngine = new Pkcs1Encoding(new RsaEngine());
decryptEngine.Init(false, keyPair.Private);
var decrypted = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(bytesToDecrypt, 0, bytesToDecrypt.Length));
How do I read RSA public key from PEM file and use it to encrypt in BouncyCastle in C#?
You're using the wrong PemReader
, you want the one from Org.BouncyCastle.OpenSsl
.
EDIT: For some reason OP is insistent that this class has no ReadObject
method. It does, and it can be seen here.
Like this:
using System;
using System.IO;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
namespace ScratchPad
{
class MainClass
{
public static void Main(string[] args)
{
var pemReader = new PemReader(File.OpenText(@"/Users/horton/tmp/key-examples/myserver_pub.pem"));
var pemObject = (Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters)pemReader.ReadObject();
var rsa = DotNetUtilities.ToRSA(pemObject);
// ... more stuff ...
}
}
}
RSA Encryption in C# PEM format
The posted key is an RSA key in X.509/SPKI format. PemReader
expects a PEM encoded key. However, the posted key is not PEM encoded, it is missing header, footer and line breaks after every 64 characters. The PEM encoded key looks like this:
string publicKey = @"-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlUCQZso6P43gKqw0CfTl
wYb3N+m4v6IME4nPA3WXe52wFpDM/JCFWSdXa7BewlwzDYjblgwL4u59CPxNTPTh
7LTD4xXOaGDJHjX5+YgqK4fb9rsImjMpIACrND/LAdrq5mctWWzw3UtW3F+o+sNw
IZM8n65ysS+Vhq9IypFlfuQbWrKjAcWZ3u1iLtplzyf/pjhOEyyZiBUnh6D219+p
MiE9nhCpc4xkH1gnlGszIDBqZMMULtGJvFXydA1vv5HxxCYJ2ydEzmAKYxVgA9BG
XPEGE89dQbeJsieTj+FSsp9oTm+4vi345opRvH8DWhmZc4OPSwBEL8pwgS7cUnKP
twIDAQAB
-----END PUBLIC KEY-----";
Regarding line breaks PemReader
is tolerant: Only header and footer must be in separate lines.
Btw, as of .NET Core 3.0, import of a DER encoded RSA key in X.509/SPKI format is supported by RSA.ImportSubjectPublicKeyInfo()
. As of .NET 5, import of PEM encoded RSA keys is supported with RSA.ImportFromPem()
.
Decrypting with private key from .pem file in c# with .NET crypto library
http://www.jensign.com/opensslkey/index.html
with source at http://www.jensign.com/opensslkey/opensslkey.cs
Update: Source code is no longer available at this url. It can be found at https://gist.github.com/stormwild/7887264 or https://web.archive.org/web/20170731015547/http://www.jensign.com/opensslkey/opensslkey.cs now.
edit: excerpted relevant code:
first, extract the text between the ---- BEGIN ---- and ---- END ---- sections, and base64-decode it into a byte array (see link above for details), then pass it to:
//------- Parses binary ans.1 RSA private key; returns RSACryptoServiceProvider ---
public static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
{
byte[] MODULUS, E, D, P, Q, DP, DQ, IQ ;
// --------- Set up stream to decode the asn.1 encoded RSA private key ------
MemoryStream mem = new MemoryStream(privkey) ;
BinaryReader binr = new BinaryReader(mem) ; //wrap Memory Stream with BinaryReader for easy reading
byte bt = 0;
ushort twobytes = 0;
int elems = 0;
try {
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return null;
twobytes = binr.ReadUInt16();
if (twobytes != 0x0102) //version number
return null;
bt = binr.ReadByte();
if (bt !=0x00)
return null;
//------ all private key components are Integer sequences ----
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) ;
Console.WriteLine("showing components ..");
if (verbose) {
showBytes("\nModulus", MODULUS) ;
showBytes("\nExponent", E);
showBytes("\nD", D);
showBytes("\nP", P);
showBytes("\nQ", Q);
showBytes("\nDP", DP);
showBytes("\nDQ", DQ);
showBytes("\nIQ", IQ);
}
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
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();
}
}
Related Topics
How Create a New Deep Copy (Clone) of a List<T>
How to Send Emails Through Ssl Smtp with the .Net Framework
Difference Between Events and Delegates and Its Respective Applications
Prevent .Net Garbage Collection for Short Period of Time
Oledbcommand Parameters Order and Priority
Tolist()-- Does It Create a New List
How to Automatically Filter Out Soft Deleted Entities with Entity Framework
Executenonquery: Connection Property Has Not Been Initialized
Decompressing Gzip Stream from Httpclient Response
How to Both Read and Write a File in C#
How to Rotate a Picture in Winforms
Type or Namespace Name Does Not Exist
Xml Serialization - Disable Rendering Root Element of Array
Weird Error Upgrading ASP.NET MVC from 4 to 5
Populating a Razor Dropdownlist from a List<Object> in MVC