How to Load the Rsa Public Key from File in C#

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 ...
}
}
}

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 import an RSA Public Key from .NET into OpenSSL

In the .NET program create a new RSACryptoServiceProvider. Export the public key as RSAParameters and write the Modulus and Exponent values to disk. Like this:

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(4096); //4096 bit key
RSAParameters par = rsa.ExportParameters(false); // export the public key

File.WriteAllBytes(@"C:\modulus.bin", par.Modulus); // write the modulus and the exponent to disk
File.WriteAllBytes(@"C:\exponent.bin", par.Exponent);

On the C++ side you'll need to read the modulus and exponent values from disk convert them into BIGNUM values. These values will be loaded into an RSA key and then you can encrypt the plain text and write the cipher text to disk. Like this:

RSA * key;

unsigned char *modulus;
unsigned char *exp;

FILE * fp = fopen("c:\\modulus.bin", "rb"); // Read the modulus from disk
modulus = new unsigned char[512];
memset(modulus, 0, 512);
fread(modulus, 512, 1, fp);
fclose(fp);

fp = fopen("c:\\exponent.bin", "rb"); // Read the exponent from disk
exp = new unsigned char[3];
memset(exp, 0, 3);
fread(exp, 3, 1, fp);
fclose(fp);

BIGNUM * bn_mod = NULL;
BIGNUM * bn_exp = NULL;

bn_mod = BN_bin2bn(modulus, 512, NULL); // Convert both values to BIGNUM
bn_exp = BN_bin2bn(exp, 3, NULL);

key = RSA_new(); // Create a new RSA key
key->n = bn_mod; // Assign in the values
key->e = bn_exp;
key->d = NULL;
key->p = NULL;
key->q = NULL;

int maxSize = RSA_size(key); // Find the length of the cipher text

cipher = new char[valid];
memset(cipher, 0, valid);
RSA_public_encrypt(strlen(plain), plain, cipher, key, RSA_PKCS1_PADDING); // Encrypt plaintext

fp = fopen("C:\\cipher.bin", "wb"); // write ciphertext to disk
fwrite(cipher, 512, 1, fp);
fclose(fp);

Finally you can take the ciphertext and decrypt it in C# without any difficulty.

byte[] cipher = File.ReadAllBytes(@"c:\cipher.bin"); // Read ciphertext from file
byte[] plain = rsa.Decrypt(cipher, false); // Decrypt ciphertext

Console.WriteLine(ASCIIEncoding.ASCII.GetString(plain)); // Decode and display plain text

Encrypt text file using RSA public key

public  string Encryption(string strText)
{
var publicKey = "XXXXXXXXXXXXX The Key Value XXXXXXXXXXXXX";
var testData = Encoding.UTF8.GetBytes(strText);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);

// client encrypting data with a public key issued by server
rsa.FromXmlString(publicKey.ToString());

var encryptedData = rsa.Encrypt(testData, true);

var base64Encrypted = Convert.ToBase64String(encryptedData);

string retval = base64Encrypted.ToString();

if (HaxVal1.Equals(HaxVal))
{
return retval;
}
else
{
return "InvalidSignature";
}
}

How to use public key in RSA encryption C# (.net standard 2.0)

Below you find a full working code that encrypts a string with a RSA public key in XML-encoding and decrypts the ciphertext with a RSA private key (as well in XML encoding). The ciphertext is encoded in base64. Here is a link to an online compiler to see the code running: https://repl.it/@javacrypto/CpcCsharpRsaEncryptionOaepSha1String#main.cs

output:

RSA 2048 encryption OAEP SHA-1 string
plaintext: The quick brown fox jumps over the lazy dog

* * * encrypt the plaintext with the RSA public key * * *
ciphertextBase64: lFZwBN5SnlqAKEYktjjTmDUyIAFA86CDIrOyPeRLVXLIManP6wTUgZ3NBSYynfgwXTmVzhPQL3wZ6kngWIgVbl1sMOSiTt6BOvop5HwEU6ejUOrhgDzuxSnA4e8txNG0X8NZ4kt1bzE42gHlbjxHG+CYawAVYECPMyZ4Jc/n7qH8McsUh3n/KUOB2h5R6DULjf2Qfl4aQHppbEeECNmpSFJFUSu3iGBI7hacHbb+1myyLteS1o3FiBuSVbG+L7h8DEokbhE5yVTwamFF+qM+/HTWeGfE+CGC6Kb8cAucP7Zoov6e+Gr7aFYMvhrWjTvApzMBu5XD0j3JzxQD9OmA8g==

* * * decrypt the ciphertext with the RSA private key * * *
ciphertextReceivedBase64: lFZwBN5SnlqAKEYktjjTmDUyIAFA86CDIrOyPeRLVXLIManP6wTUgZ3NBSYynfgwXTmVzhPQL3wZ6kngWIgVbl1sMOSiTt6BOvop5HwEU6ejUOrhgDzuxSnA4e8txNG0X8NZ4kt1bzE42gHlbjxHG+CYawAVYECPMyZ4Jc/n7qH8McsUh3n/KUOB2h5R6DULjf2Qfl4aQHppbEeECNmpSFJFUSu3iGBI7hacHbb+1myyLteS1o3FiBuSVbG+L7h8DEokbhE5yVTwamFF+qM+/HTWeGfE+CGC6Kb8cAucP7Zoov6e+Gr7aFYMvhrWjTvApzMBu5XD0j3JzxQD9OmA8g==
decryptedData: The quick brown fox jumps over the lazy dog

Security warning: the code uses hard coded RSA [sample] keys for demonstration only. The code has no exception handling and is for educational purpose only.

using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;

class RsaEncryptionOaepSha1 {
static void Main() {
Console.WriteLine("RSA 2048 encryption OAEP SHA-1 string");
string dataToEncryptString = "The quick brown fox jumps over the lazy dog";
Console.WriteLine("plaintext: " + dataToEncryptString);

// # # # usually we would load the private and public key from a file or keystore # # #
// # # # here we use hardcoded keys for demonstration - don't do this in real programs # # #
string filenamePrivateKeyXml = "privatekey2048.xml";
string filenamePublicKeyXml = "publickey2048.xml";

try {
// encryption
Console.WriteLine("\n* * * encrypt the plaintext with the RSA public key * * *");
//string publicKeyLoad = loadRsaPublicKeyPem();
// use this in production
string publicKeyLoad = File.ReadAllText(filenamePublicKeyXml);
byte[] dataToEncrypt = Encoding.UTF8.GetBytes(dataToEncryptString);
string ciphertextBase64 = Base64Encoding(rsaEncryptionOaepSha1(publicKeyLoad, dataToEncrypt));
//string ciphertextBase64 = "";
Console.WriteLine("ciphertextBase64: " + ciphertextBase64);

// transport the encrypted data to recipient

// receiving the encrypted data, decryption
Console.WriteLine("\n* * * decrypt the ciphertext with the RSA private key * * *");
string ciphertextReceivedBase64 = ciphertextBase64;
Console.WriteLine("ciphertextReceivedBase64: " + ciphertextReceivedBase64);
//string privateKeyLoad = loadRsaPrivateKeyPem();
// use this in production
string privateKeyLoad = File.ReadAllText(filenamePrivateKeyXml);
byte[] ciphertextReceived = Base64Decoding(ciphertextReceivedBase64);
byte[] decryptedtextByte = rsaDecryptionOaepSha1(privateKeyLoad, ciphertextReceived);
Console.WriteLine("decryptedData: " + Encoding.UTF8.GetString(decryptedtextByte, 0, decryptedtextByte.Length));
}
catch(ArgumentNullException) {
Console.WriteLine("The data was not RSA encrypted");
}
}

public static byte[] rsaEncryptionOaepSha1(string publicKeyXml, byte[] plaintext) {
RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider(2048);
RSAalg.PersistKeyInCsp = false;
RSAalg.FromXmlString(publicKeyXml);
return RSAalg.Encrypt(plaintext, true);
}

public static byte[] rsaDecryptionOaepSha1(string privateKeyXml, byte[] ciphertext) {
RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider(2048);
RSAalg.PersistKeyInCsp = false;
RSAalg.FromXmlString(privateKeyXml);
return RSAalg.Decrypt(ciphertext, true);
}

static string Base64Encoding(byte[] input) {
return Convert.ToBase64String(input);
}

static byte[] Base64Decoding(String input) {
return Convert.FromBase64String(input);
}

public static string loadRsaPublicKeyPem() {
return "<RSAKeyValue><Modulus>8EmWJUZ/Osz4vXtUU2S+0M4BP9+s423gjMjoX+qP1iCnlcRcFWxthQGN2CWSMZwR/vY9V0un/nsIxhZSWOH9iKzqUtZD4jt35jqOTeJ3PCSr48JirVDNLet7hRT37Ovfu5iieMN7ZNpkjeIG/CfT/QQl7R+kO/EnTmL3QjLKQNV/HhEbHS2/44x7PPoHqSqkOvl8GW0qtL39gTLWgAe801/w5PmcQ38CKG0oT2gdJmJqIxNmAEHkatYGHcMDtXRBpOhOSdraFj6SmPyHEmLBishaq7Jm8NPPNK9QcEQ3q+ERa5M6eM72PpF93g2p5cjKgyzzfoIV09Zb/LJ2aW2gQw==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
}

public static string loadRsaPrivateKeyPem() {
return "<RSAKeyValue><Modulus>8EmWJUZ/Osz4vXtUU2S+0M4BP9+s423gjMjoX+qP1iCnlcRcFWxthQGN2CWSMZwR/vY9V0un/nsIxhZSWOH9iKzqUtZD4jt35jqOTeJ3PCSr48JirVDNLet7hRT37Ovfu5iieMN7ZNpkjeIG/CfT/QQl7R+kO/EnTmL3QjLKQNV/HhEbHS2/44x7PPoHqSqkOvl8GW0qtL39gTLWgAe801/w5PmcQ38CKG0oT2gdJmJqIxNmAEHkatYGHcMDtXRBpOhOSdraFj6SmPyHEmLBishaq7Jm8NPPNK9QcEQ3q+ERa5M6eM72PpF93g2p5cjKgyzzfoIV09Zb/LJ2aW2gQw==</Modulus><Exponent>AQAB</Exponent><P>/8atV5DmNxFrxF1PODDjdJPNb9pzNrDF03TiFBZWS4Q+2JazyLGjZzhg5Vv9RJ7VcIjPAbMy2Cy5BUffEFE+8ryKVWfdpPxpPYOwHCJSw4Bqqdj0Pmp/xw928ebrnUoCzdkUqYYpRWx0T7YVRoA9RiBfQiVHhuJBSDPYJPoP34k=</P><Q>8H9wLE5L8raUn4NYYRuUVMa+1k4Q1N3XBixm5cccc/Ja4LVvrnWqmFOmfFgpVd8BcTGaPSsqfA4j/oEQp7tmjZqggVFqiM2mJ2YEv18cY/5kiDUVYR7VWSkpqVOkgiX3lK3UkIngnVMGGFnoIBlfBFF9uo02rZpC5o5zebaDIms=</Q><DP>BPXecL9Pp6u/0kwY+DcCgkVHi67J4zqka4htxgP04nwLF/o8PF0tlRfj0S7qh4UpEIimsxq9lrGvWOne6psYxG5hpGxiQQvgIqBGLxV/U2lPKEIb4oYAOmUTYnefBCrmSQW3v93pOP50dwNKAFcGWTDRiB/e9j+3EmZm/7iVzDk=</DP><DQ>rBWkAC/uLDf01Ma5AJMpahfkCZhGdupdp68x2YzFkTmDSXLJ/P15GhIQ+Lxkp2swrvwdL1OpzKaZnsxfTIXNddmEq8PEBSuRjnNzRjQaLnqjGMtTBvF3G5tWkjClb/MW2q4fgWUG8cusetQqQn2k/YQKAOh2jXXqFOstOZQc9Q0=</DQ><InverseQ>BtiIiTnpBkd6hkqJnHLh6JxBLSxUopFvbhlR37Thw1JN94i65dmtgnjwluvR/OMgzcR8e8uCH2sBn5od78vzgiDXsqITF76rJgeO639ILTA4MO3Mz+O2umrJhrkmgSk8hpRKA+5Mf9aE7dwOzHrc8hbj8J102zyYJIE6pOehrGE=</InverseQ><D>hXGYfOMFzXX/vds8HYQZpISDlSF3NmbTCdyZkIsHjndcGoSOTyeEOxV93MggxIRUSjAeKNjPVzikyr2ixdHbp4fAKnjsAjvcfnOOjBp09WW4QCi3/GCfUh0w39uhRGZKPjiqIj8NzBitN06LaoYD6MPg/CtSXiezGIlFn/Hs+MuEzNFu8PFDj9DhOFhfCgQaIgEEr+IHdnl5HuUVrwTnIBrEzZA/08Q0Gv86qQZctZWoD9hPGzeAC+RSMyGVJw6Ls8zBFf0eysB4spsu4LUom/WnZMdS1ls4eqsAX+7AdqPKBRuUVpr8FNyRM3s8pJUiGns6KFsPThtJGuH6c6KVwQ==</D></RSAKeyValue>";
}

}


Related Topics



Leave a reply



Submit