Wednesday, March 20, 2013

Display Decrypted Data on Report.rdlc




Requirement : Creating a .rdlc report to display data in SQL database, some fields of which are in encrypted form.
Solution : Binding dataset to report at runtime.

Design Project to insert data into database in encrypted form.
To know how to use encryption please see my blog post http://encryptdecryptstring.blogspot.in/

    Now if you want to display this data on .rdlc Report you will have to decrypt the data which is fetched from database & is in encrypted form. So we cannot write function (.NET function to decrypt data) to decrypt data inside our SQL query, and if we try to write that function in a separate assembly and refer it in your report then it might possible but I was not able to do so and I was getting so many error while referring the dll inside report.
       So here I am explaining the solution where we bind the data set at run-time.

       We will create a report with a dataset created at design time but this dataset will have data in encrypted form, so we will replace this dataset with the new dataset having decrypted data(And since we are replacing this runtime dataset will have the same name which we used at design time).
Right click on your project and select "Add New Item…"Select Report.rdlc and click Add.
 













This will create a report and now we ‘Add New Dataset’ as shown below.








Select database connection (create new if required or select existing) and dataset properties as shown below.













































































































Now we will update/reset this DataSet at runtime(so note the Name provided above(in my case EmpSalaryInfo_DS) which we will use in code).

Now add new windows form to display this report.
From Toolbar add ReportViewer control (available under Reporting section) to the form.
Select reportviewer control and select its properties, select Local Report’s property and set ReportEmbeddedResource to point to above created report path as shown below.















Now select code behind of above added form(Form1.cs)

Add Following function to your class which retrieves data from your database and decrypts the encrypted column. Don’t forget to replace connectionString variable with your database connection string.

         public DataSet GetDetails()
        {
SqlConnection connection;

            try
            {
                string connectionString = "Data Source=.;Initial Catalog=SalaryDetails;Persist Security Info=True;User ID=sa;Password=root@123";
                connection = new SqlConnection(connectionString);
                connection.Open();

                SqlCommand selectCommand = new SqlCommand("select * from EmpSalaryInfo", connection);
                SqlDataAdapter da = new SqlDataAdapter(selectCommand);
                DataSet dsSalaryDetails = new DataSet();
                da.Fill(dsSalaryDetails);

                // Bind the encrypted data to datagridview.
                DataTable dtUserSalaryDetails = new DataTable();
                dtUserSalaryDetails.Load(dsSalaryDetails.CreateDataReader());
                dataGridView1.DataSource = dtUserSalaryDetails;

                // Before returning the dataset decrypt all the columns which are encrypted.
                // Here i am decrypting "AnnualSalary" column which is only encrypted column in my case.
                for (int i = 0; i < dsSalaryDetails.Tables[0].Rows.Count; i++)
                {
                    dsSalaryDetails.Tables[0].Rows[i]["AnnualSalary"] = Crypto.DecryptData(Convert.ToString(dsSalaryDetails.Tables[0].Rows[i]["AnnualSalary"]));
                }

                return dsSalaryDetails;
            }
            catch (Exception ex)
            {
                throw;
            }
            finally
            {
                connection.Close();
            }
        }

Add Following function which Loads data from database and binds the Data Datasource(which in turn consist of dataset) to the report. Here we clear the existing datasources and binds the new one at runtime.

         private void LoadReport()
        {
            try
            {
                DataSet ds = GetDetails();
                ReportDataSource rds = new ReportDataSource("EmpSalaryInfo_DS", ds.Tables[0]);
                reportViewerControl.LocalReport.DataSources.Clear();
                reportViewerControl.LocalReport.DataSources.Add(rds);
                reportViewerControl.RefreshReport();
            }
            catch (Exception ex)
            {
                throw;
            }
        }


Call this function in constructor of form so that it gets called when form loads.

         public Form1()
        {
            InitializeComponent();
            LoadReport();
        }




Output:




















Please let me know if you need source code for the same.. You can write to me on narenkedari@gmail.com

Tuesday, March 19, 2013

Encryption Decryption in .NET

       Yo can do encryption decryption using various available algorithms.
       Here i have explained encryption & decryption of a string using classes in namespace System.Security.Cryptography (available in System.Security.dll). 

       You can use it in your application to encrypt user password(or any secret information) and store it in database in encrypted form so that no one can see/hack it. 
Then while using you can retrieve this encrypted password and decrypt it to get original password.

To implement it use following steps:


   1.       Add Reference to assembly : System.Security.dll
   2.       Import namespace  System.Security.Cryptography to use cryptographic classes in it.
   3.       Add the following class in your project (if required you can name it different. i have named it as Crypto)


public static class Crypto
    {
        const string secretKey = "secretKey";
      
        /// <summary>
        /// Encrypts given string using 3DES algorithm.
        /// </summary>
        /// <param name="source">string to be encrypted.</param>
        /// <returns>encrypted string</returns>
        public static string EncryptData(string source)
        {
            try
            {
                byte[] encryptedResults;
                System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
                MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
                byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(secretKey));
                TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
                TDESAlgorithm.Key = TDESKey;
                TDESAlgorithm.Mode = CipherMode.ECB;
                TDESAlgorithm.Padding = PaddingMode.PKCS7;
                byte[] DataToEncrypt = UTF8.GetBytes(source);
                try
                {
                    ICryptoTransform encryptor = TDESAlgorithm.CreateEncryptor();
                    encryptedResults = encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
                }
                finally
                {
                    TDESAlgorithm.Clear();
                    HashProvider.Clear();
                }
                return Convert.ToBase64String(encryptedResults);
            }
            catch (Exception ex)
            {
                throw;
            }
        }


        /// <summary>
        /// Decrypts given string(in encrypted format) using 3DES algorithm.
        /// </summary>
        /// <param name="encryptedString">string to be decrypted</param>
        /// <returns>decrypted string</returns>
        public static string DecryptData(string encryptedString)
        {
            try
            {
                byte[] encryptedResults;
                System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
                MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
                byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(secretKey));
                TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
                TDESAlgorithm.Key = TDESKey;
                TDESAlgorithm.Mode = CipherMode.ECB;
                TDESAlgorithm.Padding = PaddingMode.PKCS7;
                byte[] DataToDecrypt = Convert.FromBase64String(encryptedString);
                try
                {
                    ICryptoTransform decryptor = TDESAlgorithm.CreateDecryptor();
                    encryptedResults = decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length);
                }
                finally
                {
                    TDESAlgorithm.Clear();
                    HashProvider.Clear();
                }
                return UTF8.GetString(encryptedResults);
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }