Re: Public Key Encryption with RSACryptoServiceProvider

From: AlBruAn (albruan_at_hotmail.com.(donotspam))
Date: 06/25/04


Date: Fri, 25 Jun 2004 11:55:01 -0700


"Pieter Philippaerts" wrote:

> "AlBruAn" <AlBruAn@discussions.microsoft.com> wrote in message
> > I'm attempting to use the RSACryptoServiceProvider class to encrypt some
> licensing information I'm storing in SQL Server, but I'm encountering a "Bad
> Data" CryptographicException when I try decrypting the data and wonder how I
> can get around this issue. I'm not storing any information in SQL Server
> until I can get the mechanics of encryption working properly. Anyway...
> > I've generated a pair of public and private keys using
> RSACryptoServiceProvider's ToXml function, passing false and true arguments,
> respectively, to it. I then persist these keys to the root directory of my
> C: drive using an XmlTextWriter.
> > When it's time to encrypt a license number, I create a new instance of the
> RSACryptoServiceProvider object and read in the public key using its FromXml
> function. I then call the Encrypt function, passing it the license number
> and specifying no OAEP padding. My final step is to persist the encrypted
> values to a separate file in the root directory of my C: drive.
>
> From your description, there doesn't seem to be an abvious error. Could you
> post the source code you're using so we can take a closer look?
>
> > Even tho' I'm using the string "123" as my "license number" and using the
> same
> > public key, I'm getting different values for the encrypted "license
> number".
>
> This is normal; whenever you encrypt something, the RSACryptoServiceProvider
> will add a special padding to your data to make sure the length is equal to
> the modulus size of your public key. This padding consists mostly of random
> bytes, hence the difference.
>
> Regards,
> Pieter Philippaerts
>
>
It's rather long, but here is the class I wrote to try using the RSACryptoServiceProvider:

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

namespace TryRSA
{
        class EncryptDecrypt
        {
                public void DoThis(string Msg, bool Encode)
                {
                        try
                        {
                                UnicodeEncoding ByteConverter = new UnicodeEncoding();
                                byte[] dataToEncrypt = ByteConverter.GetBytes("Data to Encrypt");
                                byte[] encryptedData;
                                byte[] decryptedData;
            
                                //Create a new instance of RSACryptoServiceProvider to generate
                                //public and private key data.
                                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024);

                                // Generate and persist the private and/or public keys
                                GenKeys(RSA, Encode);

                                if (Encode == true)
                                {
                                        encryptedData = RSAEncrypt(dataToEncrypt, false);
                                        string encoded;
                                        StreamWriter sw = new StreamWriter("C:\\Encrypted.dat");
                                        UTF8Encoding utf8 = new UTF8Encoding();
                                        encoded = utf8.GetString(encryptedData);
                                        sw.WriteLine(encoded);
                                        sw.Close();
                                }
                                else
                                {
                                        StreamReader sr = new StreamReader("C:\\Encrypted.dat");
                                        string encoded = sr.ReadLine();
                                        sr.Close();
                                        UTF8Encoding utf8 = new UTF8Encoding();
                                        encryptedData = utf8.GetBytes(encoded);
                                        decryptedData = RSADecrypt(encryptedData, false);
                                        Console.WriteLine("Decrypted plaintext: {0}", ByteConverter.GetString(decryptedData));
                                }
                        }
                        catch(ArgumentNullException)
                        {
                                Console.WriteLine("Encryption failed.");
                        }
                }

                static public byte[] RSAEncrypt(byte[] DataToEncrypt, bool DoOAEPPadding)
                {
                        try
                        {
                                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
                                RSA.FromXmlString(publicKey);
                                return RSA.Encrypt(DataToEncrypt, DoOAEPPadding);
                        }
                        catch(CryptographicException e)
                        {
                                Console.WriteLine(e.Message);
                                return null;
                        }
                }

                static public byte[] RSADecrypt(byte[] DataToDecrypt, bool DoOAEPPadding)
                {
                        try
                        {
                                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
                                RSA.FromXmlString(privateKey);
                                return RSA.Decrypt(DataToDecrypt, DoOAEPPadding);
                        }
                        catch(CryptographicException e)
                        {
                                Console.WriteLine(e.ToString());
                                return null;
                        }
                }

                static private string _publicKey;
                static private string publicKey
                {
                        get { return _publicKey; }
                        set { _publicKey = value; }
                }
                static private string _privateKey;
                static private string privateKey
                {
                        get { return _privateKey; }
                        set { _privateKey = value; }
                }

                public void GenKeys(RSACryptoServiceProvider RSA, bool Encode)
                {
                        string publicKeyFileName = "C:\\public.key";
                        string privateKeyFileName = "C:\\private.key";

                        if (Encode == true)
                        {
                                // Public key
                                if (!File.Exists(publicKeyFileName))
                                {
                                        publicKey = RSA.ToXmlString(false);

                                        FileStream FileWriter = new FileStream(publicKeyFileName, FileMode.Create);
                                        XmlTextWriter XmlWriter = new XmlTextWriter(FileWriter, System.Text.Encoding.UTF8);

                                        XmlWriter.WriteRaw(publicKey);
                                        XmlWriter.Close();
                                        FileWriter.Close();
                                }
                                else
                                {
                                        FileStream FileReader = new FileStream(publicKeyFileName, FileMode.Open);
                                        XmlTextReader XmlReader = new XmlTextReader(FileReader);
                                        XmlDocument XmlDoc = new XmlDocument();

                                        XmlDoc.Load(XmlReader);
                                        publicKey = XmlDoc.InnerXml;
                                        XmlReader.Close();
                                        FileReader.Close();
                                }
                        }
                        else
                        {
                                // Private key
                                if (!File.Exists(privateKeyFileName))
                                {
                                        privateKey = RSA.ToXmlString(true);

                                        FileStream FileWriter = new FileStream(privateKeyFileName, FileMode.Create);
                                        XmlTextWriter XmlWriter = new XmlTextWriter(FileWriter, System.Text.Encoding.UTF8);

                                        XmlWriter.WriteRaw(privateKey);
                                        XmlWriter.Close();
                                        FileWriter.Close();
                                }
                                else
                                {
                                        FileStream FileReader = new FileStream(privateKeyFileName, FileMode.Open);
                                        XmlTextReader XmlReader = new XmlTextReader(FileReader);
                                        XmlDocument XmlDoc = new XmlDocument();

                                        XmlDoc.Load(XmlReader);
                                        privateKey = XmlDoc.InnerXml;
                                        XmlReader.Close();
                                        FileReader.Close();
                                }
                        }
                }
        }
}