RSA decryption - Key does not exist - c#
I'm trying to encrypt and decrypt file with RSA. Encryption is working fine. But I get error when I'm decrypting.
Error is key does not exist.
Here is the error: http://i.imgur.com/ebF09cU.png
public byte[] RSA_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes, RSAParameters RSAKeyInfo)
{
//initialze the byte arrays to the public key information.
byte[] PublicKey = {214,46,220,83,160,73,40,39,201,155,19,202,3,11,191,178,56,
74,90,36,248,103,18,144,170,163,145,87,54,61,34,220,222,
207,137,149,173,14,92,120,206,222,158,28,40,24,30,16,175,
108,128,35,230,118,40,121,113,125,216,130,11,24,90,48,194,
240,105,44,76,34,57,249,228,125,80,38,9,136,29,117,207,139,
168,181,85,137,126,10,126,242,120,247,121,8,100,12,201,171,
38,226,193,180,190,117,177,87,143,242,213,11,44,180,113,93,
106,99,179,68,175,211,164,116,64,148,226,254,172,147};
//Values to store encrypted symmetric keys.
byte[] EncryptedSymmetricKey;
byte[] EncryptedSymmetricIV;
byte[] encryptedBytes = null;
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(_stBitov))
{
//Set RSAKeyInfo to the public key values.
RSAKeyInfo.Modulus = PublicKey;
//Import key parameters into RSA.
RSA.ImportParameters(RSAKeyInfo);
//Create a new instance of the RijndaelManaged class.
RijndaelManaged RM = new RijndaelManaged();
var key = new Rfc2898DeriveBytes(PublicKey, saltBytes, 1000);
//Encrypt the symmetric key and IV.
EncryptedSymmetricKey = RSA.Encrypt(RM.Key, false);
EncryptedSymmetricIV = RSA.Encrypt(RM.IV, false);
encryptedBytes = RSA.Encrypt(bytesToBeEncrypted, false);
}
}
return encryptedBytes;
}
RSAParameters _RSAKeyInfo;
public void EncryptFile()
{
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
//Get an instance of RSAParameters from ExportParameters function.
RSAParameters RSAKeyInfo = RSA.ExportParameters(false);
_RSAKeyInfo = RSAKeyInfo;
string path = ofd.FileName;
if (File.Exists(path))
{
string dirPath = Path.GetDirectoryName(path);
byte[] bytesToBeEncrypted = File.ReadAllBytes(path);
byte[] passwordBytes = File.ReadAllBytes(dirPath + "/KEY_" + ofd.SafeFileName);
byte[] bytesEncrypted = RSA_Encrypt(bytesToBeEncrypted, passwordBytes, RSAKeyInfo);
string fileEncrypted = dirPath + "/ENCRYPTED_" + ofd.SafeFileName;
File.WriteAllBytes(fileEncrypted, bytesEncrypted);
}
}
private void button5_Click(object sender, EventArgs e)
{
string path = ofd2.FileName;
if (File.Exists(path))
{
DecryptFile();
richTextBox4.Text = "Dekripcija uspesna";
}
else
{
richTextBox6.Text = "Datoteka ni dodana";
}
} private void richTextBox4_TextChanged(object sender, EventArgs e) { }
public byte[] RSA_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes, RSAParameters RSAKeyInfo)
{
byte[] PublicKey = {214,46,220,83,160,73,40,39,201,155,19,202,3,11,191,178,56,
74,90,36,248,103,18,144,170,163,145,87,54,61,34,220,222,
207,137,149,173,14,92,120,206,222,158,28,40,24,30,16,175,
108,128,35,230,118,40,121,113,125,216,130,11,24,90,48,194,
240,105,44,76,34,57,249,228,125,80,38,9,136,29,117,207,139,
168,181,85,137,126,10,126,242,120,247,121,8,100,12,201,171,
38,226,193,180,190,117,177,87,143,242,213,11,44,180,113,93,
106,99,179,68,175,211,164,116,64,148,226,254,172,147};
//Values to store encrypted symmetric keys.
byte[] EncryptedSymmetricKey;
byte[] EncryptedSymmetricIV;
byte[] decryptedBytes = null;
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(_stBitov))
{
//Set RSAKeyInfo to the public key values.
RSAKeyInfo.Modulus = PublicKey;
//Import key parameters into RSA.
RSA.ImportParameters(RSAKeyInfo);
//Create a new instance of the RijndaelManaged class.
RijndaelManaged RM = new RijndaelManaged();
//Encrypt the symmetric key and IV.
EncryptedSymmetricKey = RSA.Encrypt(RM.Key, false);
EncryptedSymmetricIV = RSA.Encrypt(RM.IV, false);
decryptedBytes = RSA.Decrypt(bytesToBeDecrypted, false);
}
}
return decryptedBytes;
}
public void DecryptFile()
{
string path = ofd2.FileName;
if (File.Exists(path))
{
string dirPath = Path.GetDirectoryName(path);
byte[] bytesToBeDecrypted = File.ReadAllBytes(path);
byte[] passwordBytes = File.ReadAllBytes(dirPath + "/KEY_" + ofd.SafeFileName);
byte[] bytesDecrypted = RSA_Decrypt(bytesToBeDecrypted, passwordBytes, _RSAKeyInfo);
string file = dirPath + "/DECRYPTED_" + ofd.SafeFileName;
File.WriteAllBytes(file, bytesDecrypted);
}
}
Can somebody tell me what to do that decryption is going to work.
RSA is a kind of public-key cryptography. That means you need a public key to encrypt the message and a private key to decrypt your message. It looks like you're using your public key for both encryption and decryption. Where's your private key?
It seems you're trying to do hybrid encryption with RSA+AES, but you forgot to actually use AES to encrypt the plaintext and you forgot to encrypt the symmetric key with RSA. You also need to generate the symmetric key randomly and should not be derived from the public key which is supposed to be constant and public.
The error that you presented here is the least of your problems, but as ElectroByt already said, you need to use a private key (RSACryptoServiceProvider#ExportParameters(true)) to decrypt something with RSA. In your case, you would need to decrypt with RSA to get the symmetric key to use it to decrypt the symmetric ciphertext to get the actual message back.
Related
Why does the decrypted string not match the input string?
In this code snippet I have used the RSACryptoServiceProvider class to encrypt a key and IV generated by Rfc2898DerivedBytes class. The key and IV are then decrypted, inserted into an AesManaged encryptor, and then I use the AesManaged encryptor to encrypt a string(converted into a byte array). The process is reversed to decrypt the array which succeeds but then the string returned does not match the input string. Why is this? I have already tried changing the Encoding format of the byte arrays but that did not work. I have inspected the original byte array and what it looks like after it has gone through the entire process of being encrypted and decrypted and they are identical. class EncryptionBestPracticeDemo { public static byte[] keys; public static AesManaged aesAlgorithm = new AesManaged(); public struct KeyIV { public byte[] Key { get; private set; } public byte[] IV { get; private set; } public KeyIV(byte[] key, byte[] iV) { this.Key = key; this.IV = iV; } } public static KeyIV GetEncryptedKeyAndIV() { KeyIV keySalt; var password = "Pa$$w0rd"; var salt = "S#lt"; var rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt)); aesAlgorithm.Padding = PaddingMode.None; var rgbKey = rgb.GetBytes(aesAlgorithm.KeySize / 8); var rgbIV = rgb.GetBytes(aesAlgorithm.BlockSize / 8); //Encrypt the key and IV using (var rsaProvider = new RSACryptoServiceProvider()) { var setOaemPadding = true; keys = rsaProvider.ExportCspBlob(true); keySalt = new KeyIV(rsaProvider.Encrypt(rgbKey, setOaemPadding), rsaProvider.Encrypt(rgbIV, setOaemPadding)); } return keySalt; } public static void AesWithRSA() { //Use RSACryptoProvider to decrypt the secret key of the AesAlgorithm algorithm var message = "NET Cryptography"; var messageByteArray = Encoding.UTF8.GetBytes(message); byte[] encryptedData; byte[] decryptedData; //Get the encrypted Key and IV var keySalt = GetEncryptedKeyAndIV(); using (var rsaProvider = new RSACryptoServiceProvider()) { var setOaemPadding = true; rsaProvider.ImportCspBlob(keys); //Decrypt the key and IV var key = rsaProvider.Decrypt(keySalt.Key, setOaemPadding); var iV = rsaProvider.Decrypt(keySalt.IV, setOaemPadding); //Use the decrypted key and IV in the AES encryptor var encryptor = aesAlgorithm.CreateEncryptor(key, iV); using (var bufferStream = new MemoryStream()) using (var cryptoStream = new CryptoStream(bufferStream, encryptor, CryptoStreamMode.Write)) { cryptoStream.Write(messageByteArray, 0, messageByteArray.Length); encryptedData = bufferStream.ToArray(); } } using (var rsaProvider = new RSACryptoServiceProvider()) { var setOaemPadding = true; rsaProvider.ImportCspBlob(keys); //Decrypt the key and IV var key = rsaProvider.Decrypt(keySalt.Key, setOaemPadding); var iV = rsaProvider.Decrypt(keySalt.IV, setOaemPadding); //Use the decrypted key and IV in the AES decryptor var decryptor = aesAlgorithm.CreateEncryptor(key, iV); using (var bufferStream = new MemoryStream()) using (var cryptoStream = new CryptoStream(bufferStream, decryptor, CryptoStreamMode.Write)) { cryptoStream.Write(encryptedData, 0, encryptedData.Length); decryptedData = bufferStream.ToArray(); Console.WriteLine(Encoding.UTF8.GetString(decryptedData)); } } } } Input string: "NET Cryptography". Expected output string: "NET Cryptography". Output string: "????b!?k?!? ?+X".
C#: Error while decoding OAEP padding weird issue
I'm currently working on a class that encrypts large amounts of text with a randomly generated encryption key encrypted by a X509 certificate from a smart card, using a RSACryptoServiceProvider to perform the master key encryption and decryption operations. However, when I have the fOEAP padding option set to true, I have the "Error while decoding OAEP padding" error on decryption every time. I've checked the key size and it is within acceptable limits. And I've gone through breakpoints to make sure that the Base64 string that gets returned from the encryption function is the exact same as the encrypted Base64 string that gets passed back to the decryption function when the file gets loaded again. The key pair is definitely correct, since it works fine without OAEP. And I've checked the text encoding too. EDIT: It turns out this could be a smart card specific issue, when I tried decryption with a local X509 certificate the decryption succeeded. EDIT: This is the decryption code that fails: string TestString = "Hello World!"; X509Certificate2 cert = DRXEncrypter.GetCertificate("Select a test certificate", "Select a certificate to use for this test from the local store."); string key = DRXEncrypter.GenerateEncryptionKey(214); Console.WriteLine("Encryption Key: " + key); string encrypted = DRXEncrypter.EncryptBody(TestString, key); Console.WriteLine("Encrypted Body: " + encrypted); string cryptokey = DRXEncrypter.EncryptWithCert(cert, key); Console.WriteLine("Encrypted Decryption Key: " + cryptokey); string decrypted = DRXEncrypter.DecryptBody(encrypted, cryptokey, cert); Console.WriteLine("Decrypted Body: " + decrypted); Console.WriteLine("Output String: " + decrypted + "."); Here is the code from the crypto provider class I've written. I've been stuck on this issue for hours, so it would be great if someone could help me out. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.IO; namespace CoreDRXEditor { public class DRXEncrypter { private byte[] Salt = Encoding.ASCII.GetBytes("81PO9j8I1a94j"); private string EncryptionKey; private const bool UseOAEP = true; public DRXEncrypter(string EncryptionKey) { this.EncryptionKey = EncryptionKey; } public static string EncryptBody(string body, string encryptionkey) { // Use the plaintext master key to encrypt the body. DRXEncrypter enc = new DRXEncrypter(encryptionkey); // Encrypt the body. return enc.Encrypt(body); } public static int GetMaxKeySize(X509Certificate2 cert) { RSACryptoServiceProvider csp = cert.PublicKey.Key as RSACryptoServiceProvider; return csp.KeySize; } public static string DecryptBody(string body, string encryptionkey, X509Certificate2 cert) { // Decrypt the encrypted encryption key with the certificate. string DecryptedKey = Convert.ToBase64String(DecryptWithCert(cert, encryptionkey)); // Create a new DRXEncrypter using the decrypted encryption key to decrypt the body. DRXEncrypter enc = new DRXEncrypter(DecryptedKey); // Return the decrypted body. return enc.Decrypt(body); } public static string GenerateEncryptionKey(int KeyLength) { using (RandomNumberGenerator rng = new RNGCryptoServiceProvider()) { byte[] CryptoBytes = new byte[KeyLength]; rng.GetBytes(CryptoBytes); return Convert.ToBase64String(CryptoBytes); } } public static X509Certificate2 GetCertificate(string title, string message) { X509Store cstore = new X509Store(StoreLocation.CurrentUser); cstore.Open(OpenFlags.ReadOnly); X509CertificateCollection certs = X509Certificate2UI.SelectFromCollection(cstore.Certificates, title, message, X509SelectionFlag.SingleSelection); if (certs.Count == 1) { X509Certificate2 mcert = certs[0] as X509Certificate2; return mcert; } else { return null; } } public static string EncryptWithCert(X509Certificate2 cert, string PlainText) { RSACryptoServiceProvider csp = cert.PublicKey.Key as RSACryptoServiceProvider; byte[] PlainBytes = Convert.FromBase64String(PlainText); // This converts the plain text into a byte array and then encrypts the raw bytes. byte[] CryptoBytes = csp.Encrypt(PlainBytes, UseOAEP); // This converts the encrypted bytes into a Base64 string. string ReturnString = Convert.ToBase64String(CryptoBytes); return ReturnString; } public static byte[] DecryptWithCert(X509Certificate2 cert, string EncryptedText) { RSACryptoServiceProvider csp = cert.PrivateKey as RSACryptoServiceProvider; //CspParameters csps = new CspParameters(); byte[] EncryptedBytes = Convert.FromBase64String(EncryptedText); // This converts the encrypted, Base64 encoded byte array from EncryptWithCert() to a byte[] and decrypts it. byte[] CryptoBytes = csp.Decrypt(EncryptedBytes, UseOAEP); return CryptoBytes; } public string Encrypt(string PlainText) { RijndaelManaged Algorithm = null; string Output = null; try { Rfc2898DeriveBytes PrivateKey = new Rfc2898DeriveBytes(this.EncryptionKey, this.Salt); Algorithm = new RijndaelManaged(); Algorithm.Key = PrivateKey.GetBytes(Algorithm.KeySize / 8); Algorithm.Padding = PaddingMode.PKCS7; ICryptoTransform Encryption = Algorithm.CreateEncryptor(Algorithm.Key, Algorithm.IV); using (MemoryStream msa = new MemoryStream()) { msa.Write(BitConverter.GetBytes(Algorithm.IV.Length), 0, sizeof(int)); msa.Write(Algorithm.IV, 0, Algorithm.IV.Length); using (CryptoStream csa = new CryptoStream(msa, Encryption, CryptoStreamMode.Write)) { using (StreamWriter swa = new StreamWriter(csa)) { swa.Write(PlainText); } } Output = Convert.ToBase64String(msa.ToArray()); } } finally { if (Algorithm != null) { Algorithm.Clear(); } } return Output; } public string Decrypt(string EncryptedText) { RijndaelManaged Algorithm = null; string Output = null; try { Rfc2898DeriveBytes PrivateKey = new Rfc2898DeriveBytes(this.EncryptionKey, this.Salt); byte[] KeyBytes = Convert.FromBase64String(EncryptedText); using (MemoryStream msb = new MemoryStream(KeyBytes)) { Algorithm = new RijndaelManaged(); Algorithm.Key = PrivateKey.GetBytes(Algorithm.KeySize / 8); Algorithm.IV = ReadByteArray(msb); Algorithm.Padding = PaddingMode.PKCS7; ICryptoTransform Decryption = Algorithm.CreateDecryptor(Algorithm.Key, Algorithm.IV); using (CryptoStream csb = new CryptoStream(msb, Decryption, CryptoStreamMode.Read)) { using (StreamReader srb = new StreamReader(csb)) { Output = srb.ReadToEnd(); } } } } finally { if (Algorithm != null) { Algorithm.Clear(); } } return Output; } public static string Sha512(string ToHash) { using (SHA512 SHA = new SHA512Managed()) { byte[] HashByte = Encoding.UTF8.GetBytes(ToHash); byte[] HashBytes = SHA.ComputeHash(HashByte); string Hash = System.Text.Encoding.UTF8.GetString(HashBytes, 0, HashBytes.Length); return Hash; } } public static string Base64Encode(string data) { byte[] str = Encoding.UTF8.GetBytes(data); return Convert.ToBase64String(str); } public static string Base64Decode(string data) { byte[] str = Convert.FromBase64String(data); return Encoding.UTF8.GetString(str); } private byte[] ReadByteArray(Stream st) { byte[] Length = new byte[sizeof(int)]; st.Read(Length, 0, Length.Length); byte[] Buffer = new byte[BitConverter.ToInt32(Length, 0)]; st.Read(Buffer, 0, Buffer.Length); return Buffer; } } }
I've been arguing with this today with smartcards (or more accurately, a Yubikey Neo with the smartcard PIV applet enabled); using this code: var encryptor = (RSACryptoServiceProvider)c.PublicKey.Key; var decryptor = (RSACryptoServiceProvider)c.PrivateKey; var encrypt = encryptor.Encrypt(bytes, RSAEncryptionPadding.Pkcs1); var decrypt = decryptor.Decrypt(encrypt, RSAEncryptionPadding.Pkcs1); I've found that it matters what padding algo I use. If I use PKCS1 padding, everything works. If I use OaepSHA1, I get the Error while decoding [...] error. If I use anything else (e.g., OaepSHA256) I get a Not supported error. I can only conclude that my smartcard doesn't properly support OAEP SHA1, but padding with PKCS#1 everything is good. Even if this answers what you already know, it may be useful as another datapoint for anyone else coming along using smartcards.
Make sure your key size is not too small or too large. See comments from MSDN The RSACryptoServiceProvider supports key sizes from 384 bits to 16384 bits in increments of 8 bits if you have the Microsoft Enhanced Cryptographic Provider installed. It supports key sizes from 384 bits to 512 bits in increments of 8 bits if you have the Microsoft Base Cryptographic Provider installed. So you might need to pad short key strings with some bytes to get the minimum key length
Ok, I managed to check this and from what I can see, I have problems with some certificates. I am not sure why some certificates work while others don't. It would be good to know why some certificates fail in this case? Anyway, I created a new self signed certificate using windows "Manage File Encryption Certificates" and used this certificate, and all seems to work. The out put from your code. Encryption Key: aUc/GXWDoh2LktaEGeCJfju1dHP118yD/fzfT0iJLuhOq2QeyGpG6m3aBHaxvdH0ufeXRHbMjmlmPgIL/bhABzkT2C5Oa6ZhY3IFXb5t7JXZ3AtUunvtNAnRyFJ7MzklrSZGgQ vF67DSNfIVE17doKt6j6mkCpSco56ooZCrOs2Mp3vSXqNjvjiwMEfQbk41aYUNVNVNlBGhdNQCIZIAKezQCUpWqzn2II27FIDfqDIEW4ieyzpXC05GzUlGXDxFOiFUPk3n0Y94vgeF8AlCD74eyZtz WQ== Encrypted Body: EAAAANS/W7+GGRbT1q5NCYvZlDZYtxaA8g55HzUqP5qxhenn Encrypted Decryption Key: vc/tcsApmY1503BFi7oSu/RDvZivA1Ed58KJuLoEC6eE8q0BIa6ye2JvtXyxkVbzzL0MA51pZ2ZhMIsfCnBsEDjCgy+JLTZTGM1Mv+em9frFUKb0zHbICnPUa/3H yd1yOWsdn5ws19QN2dzC6eau+ExhT2T/vyZO4Nf9NdHKnB8n2yB1rrQ/T+N2EYCNH/AVPDAsme6JG7k9Od2XIipBXMyCgXgWYZmQusq+JQjA9d3c4CrQYcg/ERF+K3oZv/gPicBkAR5taxwSxAajGg bpkJNsbhTMHTN9bOn333qZ6ojlo5e882baZXuZWPr9qtj1b7ONoOyuSx/OvGKjt93BQg== Decrypted Body: Hello World! Output String: Hello World!. Hope that helps
Error "InvalidCipherTextException: data start wrong 64" with Bouncy Castle
I am encrypting and decrypting some Data using BouncyCastle, but when the lenght of the word is too long (i don´t know exactly the value), i got this error "InvalidCipherTextException: data start wrong 64" This is my Class of Encription: public static class Crypto { public static IAsymmetricBlockCipher CriarCipher(byte[] encodingParam) { // Creating the RSA algorithm object IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine(), new Sha256Digest(), encodingParam); return cipher; } public static AsymmetricCipherKeyPair CreatePair() { RsaKeyPairGenerator rsaKeyPairGnr = new RsaKeyPairGenerator(); rsaKeyPairGnr.Init(new KeyGenerationParameters(new SecureRandom(), 1024)); AsymmetricCipherKeyPair keyPair = rsaKeyPairGnr.GenerateKeyPair(); return keyPair; } public static byte[] Encriptar(RsaKeyParameters publicKey, string texto, byte[] encodingParam) { // Creating the RSA algorithm object IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine(), new Sha256Digest(), encodingParam); var palavrabyte = Encoding.UTF8.GetBytes(texto); // Initializing the RSA object for Encryption with RSA public key. Remember, for encryption, public key is needed cipher.Init(true, publicKey); byte[] ciphered = cipher.ProcessBlock(palavrabyte, 0, palavrabyte.Length); return ciphered; } public static string Decriptar(RsaKeyParameters privateKey, string txtEncript, byte[] encodingParam) { // Creating the RSA algorithm object IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine(), new Sha256Digest(), encodingParam); // Initializing the RSA object for Encryption with RSA public key. Remember, for encryption, public key is needed cipher.Init(false, privateKey); byte[] txtEncriptBytes = Convert.FromBase64String(txtEncript); byte[] deciphered = cipher.ProcessBlock(txtEncriptBytes, 0, txtEncriptBytes.Length); string decipheredText = Encoding.UTF8.GetString(deciphered, 0, deciphered.Length); return decipheredText; } } This is the code for OAEPE Encoding: SHA256Managed Hash = new SHA256Managed(); byte[] ParamOEAP = Hash.ComputeHash("Example" + anotherdata); And the class SHA256Managed: public class SHA256Managed { public byte[] ComputeHash(string text) { Sha256Digest dig = new Sha256Digest(); byte[] msgBytes = Encoding.UTF8.GetBytes(text); dig.BlockUpdate(msgBytes, 0, msgBytes.Length); byte[] result = new byte[dig.GetDigestSize()]; dig.DoFinal(result, 0); return result; } } When i encrypt the word, per example, "Subtracão de Incapazes", the decryption its ok. When i encrypt the word, per example, "Estelionato por Emissão de Cheque sem Suficiente Provisão de Fundos", the decryption brokes in the Decriptar codeline: byte[] deciphered = cipher.ProcessBlock(txtEncriptBytes, 0, txtEncriptBytes.Length); What i am doing wrong ?
Changing on CreatePair the line: rsaKeyPairGnr.Init(new KeyGenerationParameters(new SecureRandom(), 2048)) From 1024 to 2048 !! Now, big phrases are decrypted.
C# Extracting a rsa public key from .cer (2048-bit) certificate and encrypting data using RSA/ECB/PKCS1Padding method
`I have imported the .cer certificate through IIS manager->Server Certificates-> import I want to extract the public key from a .cer certificate (link) and encrypt a string using the public key(RSA 2048 bit) extracted from the certificate,the method used should be RSA with ECB and PKCS1Padding edit:added the below code public static void SettingRSAParameters(){ X509Certificate cert = X509Certificate.CreateFromCertFile("D:\\cer.cer"); byte[] publicKey = cert.GetPublicKey(); int keyLength = publicKey.Length; byte[] ExponentData = new byte[3]; byte[] ModulusData = new byte[256]; Array.Copy(publicKey, publicKey.Length - ExponentData.Length, ExponentData, 0, ExponentData.Length); Array.Copy(publicKey, publicKey.Length - ExponentData.Length - 2 - ModulusData.Length, ModulusData, 0, ModulusData.Length); ExponentData1 = ExponentData; ModulusData1 = ModulusData;} Extracting the modulus and exponent data in this fashion and plugging it in through the below code static public byte[] Encryption(byte[] Data, RSAParameters RSAKey, bool DoOAEPPadding) { SettingRSAParameters(); RSAKey.Modulus = ModulusData1; RSAKey.Exponent = ExponentData1; try { byte[] encryptedData; using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(2048)) { RSA.ImportParameters(RSAKey); encryptedData = RSA.Encrypt(Data, DoOAEPPadding); return encryptedData; } } catch (CryptographicException e) { Console.WriteLine(e.Message); return null; } } The code doesn't encrypt properly please check if the code is correct and also suggest as where to add the ciphermode ECB
Read RSA PrivateKey in C# and Bouncy Castle
I have successfully written to public and private key files with OpenSSL format. Files: -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpHCHYgawzNlxVebSKXL7vfc/i hP+dQgMxlaPEi7/vpQtV2szHjIP34MnUKelXFuIETJjOgjWAjTTJoj38MQUWc3u7 SRXaGVggqQEKH+cRi5+UcEObIfpi+cIyAm9MJqKabfJK2e5X/OS7FgAwPjgtDbZO ZxamOrWWL8KGB+lH+QIDAQAB -----END PUBLIC KEY----- -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCpHCHYgawzNlxVebSKXL7vfc/ihP+dQgMxlaPEi7/vpQtV2szH jIP34MnUKelXFuIETJjOgjWAjTTJoj38MQUWc3u7SRXaGVggqQEKH+cRi5+UcEOb Ifpi+cIyAm9MJqKabfJK2e5X/OS7FgAwPjgtDbZOZxamOrWWL8KGB+lH+QIDAQAB AoGBAIXtL6jFWVjdjlZrIl4JgXUtkDt21PD33IuiVKZNft4NOWLu+wp17/WZYn3S C2fbSXfaKZIycKi0K8Ab6zcUo0+QZKMoaG5GivnqqTPVAuZchkuMUSVgjGvKAC/D 12/b+w+Shs9pvqED1CxfvtePXNwL6ZNuaREFC5hF/YpMVyg5AkEA3BUCZYJ+Ec96 2cwsdY6HocW8Kn+RIqMjkNtyLA19cQV5mpIP7kAiW6drBDlraVANi+5AgK2zQ+ZT hYzs/JfRKwJBAMS1g5/B7XXnfC6VTRs8AMveZudi5wS/aGpaApybsfx1NTLLsm3l GmGTkbCr+EPzvJ5zRSIAHAA6N6NdORwzEWsCQHTli+JTD5dyNvScaDkAvbYFi06f d32IXYnBpcEUYT65A8BAOMn5ssYwBL23qf/ED431vLkcig1Ut6RGGFKKaQUCQEfa UdkSWm39/5N4f/DZyySs+YO90csfK8HlXRzdlnc0TRlf5K5VyHwqDkatmoMfzh9G 1dLknVXL7jTjQZA2az8CQG0jRSQ599zllylMPPVibW98701Mdhb1u20p1fAOkIrz +BNEdOPqPVIyqIP830nnFsJJgTG2eKB59ym+ypffRmA= -----END RSA PRIVATE KEY----- And public key contains just the public key portion of course. After encrypting my message using the public key. I want to read the private key file and decrypt it but it's not working. I'm getting exceptions trying to read the private key saying can't cast object to asymmetriccipherkey. Here is my code: public static AsymmetricKeyParameter ReadAsymmetricKeyParameter(string pemFilename) { var fileStream = System.IO.File.OpenText(pemFilename); var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(fileStream); var KeyParameter = (Org.BouncyCastle.Crypto.AsymmetricKeyParameter)pemReader.ReadObject(); return KeyParameter; } static void Encrypt2(string publicKeyFileName, string inputMessage, string encryptedFileName) { UTF8Encoding utf8enc = new UTF8Encoding(); FileStream encryptedFile = null; try { // Converting the string message to byte array byte[] inputBytes = utf8enc.GetBytes(inputMessage); // RSAKeyPairGenerator generates the RSA Key pair based on the random number and strength of key required /*RsaKeyPairGenerator rsaKeyPairGnr = new RsaKeyPairGenerator(); rsaKeyPairGnr.Init(new Org.BouncyCastle.Crypto.KeyGenerationParameters(new SecureRandom(), 512)); Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair keyPair = rsaKeyPairGnr.GenerateKeyPair(); */ AsymmetricKeyParameter publicKey = ReadAsymmetricKeyParameter(publicKeyFileName); // Creating the RSA algorithm object IAsymmetricBlockCipher cipher = new RsaEngine(); // Initializing the RSA object for Encryption with RSA public key. Remember, for encryption, public key is needed cipher.Init(true, publicKey); //Encrypting the input bytes byte[] cipheredBytes = cipher.ProcessBlock(inputBytes, 0, inputMessage.Length); //Write the encrypted message to file // Write encrypted text to file encryptedFile = File.Create(encryptedFileName); encryptedFile.Write(cipheredBytes, 0, cipheredBytes.Length); } catch (Exception ex) { // Any errors? Show them Console.WriteLine("Exception encrypting file! More info:"); Console.WriteLine(ex.Message); } finally { // Do some clean up if needed if (encryptedFile != null) { encryptedFile.Close(); } } } Here is the decrypt function. 2nd one is without using Bouncy Castle, however, I'd rather use Bouncy Castle since later I'll be also encrypting and decrypting in Java. static void Decrypt2(string privateKeyFileName, string encryptedFileName, string plainTextFileName) { UTF8Encoding utf8enc = new UTF8Encoding(); FileStream encryptedFile = null; StreamWriter plainFile = null; byte[] encryptedBytes = null; string plainText = ""; try { // Converting the string message to byte array //byte[] inputBytes = utf8enc.GetBytes(inputMessage); // RSAKeyPairGenerator generates the RSA Key pair based on the random number and strength of key required /*RsaKeyPairGenerator rsaKeyPairGnr = new RsaKeyPairGenerator(); rsaKeyPairGnr.Init(new Org.BouncyCastle.Crypto.KeyGenerationParameters(new SecureRandom(), 512)); Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair keyPair = rsaKeyPairGnr.GenerateKeyPair(); */ StreamReader sr = File.OpenText(privateKeyFileName); PemReader pr = new PemReader(sr); PemReader pemReader = new PemReader(new StringReader(privateKeyFileName)); AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject(); Console.WriteLine(keyPair.ToString()); AsymmetricKeyParameter privatekey = keyPair.Private; Console.WriteLine(pr.ReadPemObject()); AsymmetricCipherKeyPair KeyPair = (AsymmetricCipherKeyPair)pr.ReadObject(); AsymmetricKeyParameter privateKey = ReadAsymmetricKeyParameter(privateKeyFileName); // Creating the RSA algorithm object IAsymmetricBlockCipher cipher = new RsaEngine(); Console.WriteLine("privateKey: " + privateKey.ToString()); // Initializing the RSA object for Decryption with RSA private key. Remember, for decryption, private key is needed //cipher.Init(false, KeyPair.Private); //cipher.Init(false, KeyPair.Private); cipher.Init(false, keyPair.Private); // Read encrypted text from file encryptedFile = File.OpenRead(encryptedFileName); encryptedBytes = new byte[encryptedFile.Length]; encryptedFile.Read(encryptedBytes, 0, (int)encryptedFile.Length); //Encrypting the input bytes //byte[] cipheredBytes = cipher.ProcessBlock(inputBytes, 0, inputMessage.Length); byte[] cipheredBytes = cipher.ProcessBlock(encryptedBytes, 0, encryptedBytes.Length); //Write the encrypted message to file // Write encrypted text to file plainFile = File.CreateText(plainTextFileName); plainText = Encoding.Unicode.GetString(cipheredBytes); plainFile.Write(plainText); } catch (Exception ex) { // Any errors? Show them Console.WriteLine("Exception encrypting file! More info:"); Console.WriteLine(ex.Message); } finally { // Do some clean up if needed if (plainFile != null) { plainFile.Close(); } if (encryptedFile != null) { encryptedFile.Close(); } } } // Decrypt a file static void Decrypt(string privateKeyFileName, string encryptedFileName, string plainFileName) { // Variables CspParameters cspParams = null; RSACryptoServiceProvider rsaProvider = null; StreamReader privateKeyFile = null; FileStream encryptedFile = null; StreamWriter plainFile = null; string privateKeyText = ""; string plainText = ""; byte[] encryptedBytes = null; byte[] plainBytes = null; try { // Select target CSP cspParams = new CspParameters(); cspParams.ProviderType = 1; // PROV_RSA_FULL //cspParams.ProviderName; // CSP name rsaProvider = new RSACryptoServiceProvider(cspParams); // Read private/public key pair from file privateKeyFile = File.OpenText(privateKeyFileName); privateKeyText = privateKeyFile.ReadToEnd(); // Import private/public key pair rsaProvider.FromXmlString(privateKeyText); // Read encrypted text from file encryptedFile = File.OpenRead(encryptedFileName); encryptedBytes = new byte[encryptedFile.Length]; encryptedFile.Read(encryptedBytes, 0, (int)encryptedFile.Length); // Decrypt text plainBytes = rsaProvider.Decrypt(encryptedBytes, false); // Write decrypted text to file plainFile = File.CreateText(plainFileName); plainText = Encoding.Unicode.GetString(plainBytes); plainFile.Write(plainText); } catch (Exception ex) { // Any errors? Show them Console.WriteLine("Exception decrypting file! More info:"); Console.WriteLine(ex.Message); } finally { // Do some clean up if needed if (privateKeyFile != null) { privateKeyFile.Close(); } if (encryptedFile != null) { encryptedFile.Close(); } if (plainFile != null) { plainFile.Close(); } } } // Decrypt
I figured this out. Basically to read a private openssl key using BouncyCastle and C# is like this: static AsymmetricKeyParameter readPrivateKey(string privateKeyFileName) { AsymmetricCipherKeyPair keyPair; using (var reader = File.OpenText(privateKeyFileName)) keyPair = (AsymmetricCipherKeyPair)new PemReader(reader).ReadObject(); return keyPair.Private; } Then this key can be used to decrypt data such as below: AsymmetricKeyParameter key = readPrivateKey(pemFilename); RsaEngine e = new RsaEngine(); e.Init(false, key); byte[] decipheredBytes = e.ProcessBlock(cipheredData, 0, cipheredData.Length);