Saturday, August 6, 2016

Json Serializer | Serializing Interface and Generic List

Json Serialization though can be very easy but there are situations when it is not very straight forward, specially when it is one of the following cases:
1. An interface object
2. List of objects
3. IList of objects
4. List of interface
5. IList of interface

So, you can utilize the generic code below to solve the problem:

You need to install Newtonsoft.JSON to use this code:


using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;

namespace Utilities.Core
{
    public static class JsonSerializer<T> where T : class
    {
        public static string ToJson(T objectToSerialize)
        {
            if (null == objectToSerialize)
                return null;
            return JsonConvert.SerializeObject(objectToSerialize);
        }

        public static T ToObject(string json)
        {
            if (string.IsNullOrWhiteSpace(json))
                return null;
            return JsonConvert.DeserializeObject<T>(json);
        }

        public static List<T> ToObjectList(string json)
        {
            if (string.IsNullOrWhiteSpace(json))
                return null;
            return JsonConvert.DeserializeObject<List<T>>(json);
        }
    }

    public static class JsonSerializer<TImplementation, TInterface> where TImplementation : class, TInterface
    {
        public static string ToJson(TInterface objectToSerialize)
        {
            if (null == objectToSerialize)
                return null;
            return JsonConvert.SerializeObject(objectToSerialize);
        }

        public static TInterface ToObject(string json)
        {
            return JsonSerializer<TImplementation>.ToObject(json);
        }

        public static IList<TInterface> ToObjectList(string json)
        {
            if (string.IsNullOrWhiteSpace(json))
                return null;
            var results = JsonConvert.DeserializeObject<List<TImplementation>>(json);
            IList<TInterface> objectList = results.Select(item => (TInterface) item).ToList();
            return objectList;
        }
    }
}

Thursday, January 28, 2016

Enum extensions : Some useful methods while dealing with enums

Enums are used most widely when one wants to use discrete values for a set.
Example is Currency, say I have an enum:
 
namespace EnumUtility
{
    public enum Currency
    {
        [Description("US Dollars")]
        USD,
        [Description("Indian Rupee")]
        INR
    }
}


We can have some enum extension methods for the following items:
1. Getting description for enum
2. Getting an enum if we have the corresponding description
3. Calling "Equals()" on enum to compare it to description string
4. Calling "Equals()" on description string to compare it to enum


 
using System;
using System.ComponentModel;
using System.Linq;

namespace EnumUtility
{
    public static class EnumExtensions
    {
        /// <summary>
        /// Gets the enum desciption
        /// </summary>
        /// <param name="value">Enum value</param>
        /// <returns>Description of the enum</returns>
        public static string ToDescription(this Enum value)
        {
            var fi = value.GetType().GetField(value.ToString());
            var attributes = (DescriptionAttribute[]) fi.GetCustomAttributes(typeof (DescriptionAttribute), false);
            return attributes.Length > 0 ? attributes[0].Description : value.ToString();
        }

        /// <summary>
        /// Can be called on string to convert it to Enum
        /// </summary>
        /// <typeparam name="T">Enum type</typeparam>
        /// <param name="description">Description attribute value</param>
        /// <returns>Returns the corresponding enum</returns>
        public static T ToEnum<T>(this string description)
        {
            var fields = typeof (T).GetFields();
            foreach (var field in from field
                in fields
                let attributes = (DescriptionAttribute[]) field.GetCustomAttributes
                    (typeof (DescriptionAttribute), false)
                where
                    attributes != null && attributes.Length > 0 &&
                    attributes[0].Description.ToLower().Equals(description.ToLower())
                select field)
            {
                return (T) Enum.Parse(typeof (T), field.Name);
            }

            throw new Exception("Description not found for the enum specified");
        }

        /// <summary>
        /// Can be called on enum to compare it to string
        /// </summary>
        /// <typeparam name="T">Enum type</typeparam>
        /// <param name="value">Enum value</param>
        /// <param name="description">String to compate to</param>
        /// <returns>Returns true if enum description matches string else returns false</returns>
        public static bool Equals<T>(this Enum value, string description)
        {
            var enumValue = description.ToEnum<T>();
            return value.Equals(enumValue);
        }

        /// <summary>
        /// Can be called on string to compare it to enum
        /// </summary>
        /// <typeparam name="T">Enum type</typeparam>
        /// <param name="description">Description string on which it is called</param>
        /// <param name="enumValue">Enum value to compare string to</param>
        /// <returns>Returns true if enum description matches string else returns false</returns>
        public static bool Equals<T>(this string description, T enumValue)
        {
            var newEnum = description.ToEnum<T>();
            return newEnum.Equals(enumValue);
        }
    }
}


And while we call these methods, code looks very clean:


 
using System;

namespace EnumUtility
{
    class Program
    {
        static void Main(string[] args)
        {
            string strUS = "US Dollars";

            // string to enum
            var currencyUS = strUS.ToEnum<Currency>();

            // enum to string
            Console.WriteLine(currencyUS.ToDescription());

            // enum compared to string
            Console.WriteLine(currencyUS.Equals<Currency>(strUS));

            // string compared to enum
            Console.WriteLine(strUS.Equals<Currency>(currencyUS));

            Console.ReadKey();
        }
    }
}

Thursday, January 5, 2012

Configuration files transformation for .net applications (both web and client)


Ever felt a need for different configuration files for different environments? This is a very common requirement where you want your configurations to adapt based on the environment it is built for. Let’s see how we have done it for different types of projects (web and client). What is available out of the box and what’s not?

Scenario
We have three different environments for which we change the environment specific values in the configuration file and fire the build. That’s sounds good until we ran into issues described in next section.

What is the issue?
There were two issues that we came across:
1.    We have different projects which have environment specific configuration, whenever we need a build for new environment we have to manually change the values at tons of places which is cumbersome and error-prone. It will become impossible to do once more and more projects are added which have environment specific data. To add to the pain more environments are in place for which we need to build for every deployment cycle. 
2.    For web projects, config transformation is supported out of the box but for client applications, config transformation is not supported at all. In Step 6 of “Code and Steps” below, we have followed different approaches to address this issue.


How to resolve the issue?
While resolving the issue you need to identify the environment specific data. Some of the environment specific data that we generally have is server urls, services bindings, connection strings, etc. Try to keep them in the config files of the projects. You can change the value during build based on the target build environment.
For accomplishing this while building, you can have different build configuration for different environments. Taking into account say, you have two different environments for QA and Production. You need to do the following:
1.    You need to make environment specific build configuration and add that to the solution.
2.    Update configuration in each project which has value that changes with environment.
3.    For picking up the specific configuration in the code from config files you can :
a.    Either transform config files based on the build configuration selected.
b.    Or pick altogether a different config file every time based on the build configuration selected. (You need to do this as client applications do not support config transformation.)


Code and Steps for implementing the solution

First you need to create environment specific configuration data. For accomplishing this while building, we can have different build configuration for different environments. Say, you have two different environments for QA and Production. You need to do the following:
1.    Right click on Solution and Select “Configuration Manager” :
     
2.    In Configuration Manager, select Active Solution Configuration as “New” :
    
NOTE:  You need to modify Active Solution Platform based on your environment settings.

3.    In New Solution Configuration dialog, give the name for the configuration, say “QADeploy”. Just copy the settings from any configuration you think is the similar to the current one and then you can change the values of properties opening the project file. Similarly make configuration for production, say “ProdDeploy”.
    
4.    Now if you open the project file, you can see configuration section added, something like this:
    
NOTE : The properties may differ based on your Visual Studio settings.

5.    You can add more properties or can modify existing ones based on the environment specific needs.
     
6.    Now based on the build configuration you can either transform config files or you can include all together a different config file for different configuration. Let’s see one by one how you can accomplish this.

a.    First Approach : Config Transformation
This approach is useful in case of Web.config which supports config transformation out of the box. Follow the steps listed below:
i.      In Solution Explorer, right-click the Web.config file and then click Add Config Transforms.
    
ii.     Open the transform file for the build configuration that you want to work with :
    
iii.    Edit the transform file to specify the changes that should be made to the deployed Web.config file when you deploy by using that build configuration.
The following example shows how to use the Match locator and the SetAttributes transform attribute. The Match locator attribute identifies the add element in the connectionStrings section as the element to change. The SetAttributes transform attribute specifies that this element's connectionString attribute should be changed to "NewEnvironmentSQLServer".


For more information about how to write transform files, see Web.config Transformation Syntax for Web Application Project Deployment.
iv.   Save and close the transform file.

b.    Second Approach : Including different config based on Build Configuraiton
This approach is particularly useful in case of App.config which does not support config transformation. Follow the steps listed below for including different App.config for different build configuration
i.      Add a folder named Configs in your project.
ii.     Add a folder for each environment under this folder.
iii.    Copy your App.config from project and add it in each of the folder created.
     
iv.   Make changes to the config file based on the environment, e.g. - changing the database connection strings, etc.
v.    REMOVE the following code from the project file:
<None Include="App.config" />
<None Include="Configs\Prod\App.config" />
<None Include="Configs\QA\App.config" />

vi.   ADD the following code to project file for different configurations:
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == Debug|AnyCPU' ">
    <None Include="App.config" />
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == Release|AnyCPU' ">
    <None Include="App.config" />
</ItemGroup>       
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'QADeploy|AnyCPU' ">
    <None Include="Configs\QA\App.config" />
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'ProdDeploy|AnyCPU' ">
    <None Include="Configs\Prod\App.config" />
</ItemGroup>
NOTE : Platform may differ, it can be AnyCPU, x86, x64, etc. based on your settings. Basically in the code above, its defined from which folder to pick App.Config based on the BuildConfiguration property value.

7.    You are good to build your solution using the build configuration and your environment specific configuration will automatically be picked according to the configuration specified. 

Tuesday, September 27, 2011

Digitally Signing App.config


Ever thought of putting digital signatures on Application Configuration? Here is something we went through:


Scenario
We have some values in Application Configuration file which we do want user to play around with as some of them might lead to an alternate hack of the application. We need to ensure that App.config is not tampered when used by the application. First we thought of embedding the App.config file but this is not provisioned by CLR as the file is loaded during Application Startup, so if it’s missing then application will crash. We had no option but to digitally sign the App.config file and verify the signatures on Application load. 


What is the issue?
App.config file is not any other file in the application as we cannot embed it on application assembly. So, we are left with no option than to sign it digitally and check the signatures of config file on application load. Several issues are there:

  1. Config file cannot be signed using signtool, as this is an XML file.
  2. Application crashes if I just sign the config file as config file no more abide by the schema .net CRL expects.
  3. How to ensure the signature are not tampered.

How to resolve the issue?
As config file is nothing but an XML file, we will use XMLDSIG for signing the config file. We have some classes from the framework to support the same. So, before deploying the application we’ll sign the configuration file. 
The signing of the file, adds another section to the config file – “<Signature>”. But the application fails to load because of this, as config file no more abide by the schema that .net CRL expects. So, for resolving this we add a new section declaration in “<configSections>” element before signing the config file.


For signing the App.config we’ll use asymmetric keys. We’ll use pfx certificate file for the same. The process has two steps:

  1. Signing – For this we import the pfx file in Local Computer’s Personal certificate store and then use the private key of this certificate for signing the config file. 
  2. Verify – To verify the signatures we need the corresponding public key. So, we can embed public key in the assembly and retrieve that during application load and verify the signatures on the config file.

To simplify we need to do the following things in order to sign the config file:

  1. Import pfx certificate for signing the config file
  2. Add a new <section> item to <configSections> element
  3. Execute the code for signing the config file
  4. On application load retrieve the embedded public key (.cer file)
  5. Verify the signature on config file and return the result



Code for the solution

Import the pfx file in Local Computer’s Personal certificate store


Add the following section to the <configSections> element :


<configSections>
 <section name="Signature" type="System.Configuration.IgnoreSectionHandler" />
</configSections>



Sign the config file using the console application generated by compiling the following code:


namespace SigningAppConfigConsole
{
    using System;
    using System.Text;
    using System.IO;
    using System.Linq;
    using System.Xml;
    using System.Security.Cryptography.Xml;
    using System.Security.Cryptography.X509Certificates;
    using System.Security.Cryptography;

    class Program
    {
        private static void Main(string[] args)
        {
            // Expecting first argument as path of the config file
            string path = args[0];

            // Expecting second argument as certifacte's thumbprint which will be used for signing
            string thumbprint = args[1];

            // Sign the Xml File
            SignXml(path, thumbprint);
        }

        /// 
        /// Method for signing the xml file
        /// 
        /// Path of teh file</param>
        /// Thumbprint of the certificate which should be used for signing</param>
        private static void SignXml(string path, string thumbprint)
        {
            // Check if file exists
            if (File.Exists(path))
            {
                // Loading Applcaition Configuration file as an Xml Document
                var configurationFile = new XmlDocument { PreserveWhitespace = true };
                configurationFile.Load(path);

                // Adding the transform
                var transform = new XmlDsigEnvelopedSignatureTransform();
                var reference = new Reference { Uri = string.Empty };
                reference.AddTransform(transform);

                // Creating XMLDSIG processor  
                var xmldsig = new SignedXml(configurationFile);
                xmldsig.AddReference(reference);

                // Setting signature key  
                xmldsig.SigningKey = GetPrivateKey(thumbprint);

                // Computing the signature
                xmldsig.ComputeSignature();

                // Signature XML
                var signature = xmldsig.GetXml();

                // Node to be inserted in the configuration file
                var signatureNode = configurationFile.ImportNode(signature, true);

                // Adding node to teh configuration file
                configurationFile.DocumentElement.AppendChild(signatureNode);

                // Write back the configuraiton file
                GenerateFile(path, configurationFile.InnerXml);
            }
            else
            {
                Console.WriteLine("File does not exists.");
            }
        }

        /// 
        /// Method for getting the private key of the certificate
        /// 
        /// Thumbprint of the certificate whose private key is required</param>
        /// 
        private static RSACryptoServiceProvider GetPrivateKey(string thumbprint)
        {
            // Removing spaces if thumbrint is supplied with spaces
            thumbprint = thumbprint.Replace(" ", string.Empty).ToLower();

            // StroreName.My = Personal Store, StoreLocation.LocalMachine = Local Computer Stores
            var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

            // Opening the certificate store
            store.Open(OpenFlags.ReadWrite);

            // Getting the cettificate with the mentioned thumbprint
            var x509Certificate2 = store.Certificates.Cast<X509Certificate2>().FirstOrDefault(certificate => certificate.Thumbprint.ToLower().Equals(thumbprint));

            // If certificate is not found in the store then throw exception that no certificate with
            // the mentioned thumbrint does not exists
            if (x509Certificate2 == null)
                throw new Exception("No Certificate exists with the thumbprint : " + thumbprint);

            // Returing the private key of the certificate
            if (x509Certificate2.HasPrivateKey)
            {
                var rsaCryptoServiceProvider = (RSACryptoServiceProvider)x509Certificate2.PrivateKey;

                if (rsaCryptoServiceProvider != null)
                    return rsaCryptoServiceProvider;
            }

            // Throw exception if certificate used does not have private key
            throw new Exception("Certificate used does not have private key");
        }

        /// 
        /// Method for genrating file with the passed contents
        /// 
        /// Path of the file</param>
        /// Contents</param>
        private static void GenerateFile(string filePath, string text)
        {
            // Delete file if the file with same name exists
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }

            // Writing the contents to the file
            var fileContents = new StringBuilder();
            fileContents.AppendLine(text);
            using (var outFile = new StreamWriter(filePath))
            {
                outFile.WriteLine(fileContents.ToString());
            }
        }
    }
}

The above code takes config file path and certificate’s thumbprint as input. And as output it signs the configuration file.


On Application load get the embedded public key certificate. For more details on this task follow this link – I have explained there, how to embed and get the public key certificate and ensure that it is not tampered. Once you get the certificate verify the signatures using following code:


/// 
/// Checks if the digital signature on config are valid or not
/// 
/// Returns true if signatures are valid else returns false
public static bool CheckDigitalSignature()
{
 // Get the path of the configuration file
 string configFilePath = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).FilePath;  
 
 // Loading configuration file as an Xml Document
 XmlDocument config = new XmlDocument();
 // Preserving whitespaces is important the signatures are computed considering each and every character in the file
 config.PreserveWhitespace = true;
 config.Load(configFilePath);

 // Creating XMLDSIG processor 
 SignedXml xmldsig = new SignedXml(config);

 // Getting the Signature element from the config
 XmlElement signature = (XmlElement)config.GetElementsByTagName("Signature")[0];

 // Loading XMLDSIG element into the XMLDSIG processor  
 xmldsig.LoadXml(signature);

 // Getting the public cerficate file
 X509Certificate2 certificate = new X509Certificate2(GetCertificateFile());

 // Public Key to verify the digital signatures
 RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certificate.PublicKey.Key;

 // Checking the signatures and returning the result
 return xmldsig.CheckSignature(rsa);
}

/// 
/// Get the public certificate file
/// 
/// Returns the path of the certificate file
private static string GetCertificateFile()
{
 // How to retrieve the embedded certificate can be seen in detail at :
 // http://www.rahulchugh.com/2011/09/ensuring-file-is-not-tampered-when-used.html
 string certificateFilePath = "D:\ApplicationFolder\Resources\Certificate.cer"
 return certificateFilePath;
}


Monday, September 26, 2011

Ensuring file is not tampered when used by .net code | For Thick Client Applications



Every now and then we use application files which are installed as part of your application on user’s machine. Recently, I came across the following scenario:

Scenario
We have a .net Think Client Application. Just take for example - We have a public key certificate (.cer) file which validates some signature. We want to ensure that this file is not tampered when we are using it. (I have just used certificate file as an example. It can be any file – say a pdf file which serves as a help file for my application.)

What is the issue?
As this file is part of our .net application which is installed on a user’s machine. User can change this certificate file with some of his own file, which may lead to security concerns. 

How to resolve the issue?
Let’s make it simple and split it into steps:
  1. We’ll embed the file in our assembly
  2.  Just before we want to use the file we’ll stream the file to user’s hard disk.
  3. The first time we stream the file we’ll store the MD5 hash value of the file’s content.
  4. Every time we use the file we’ll check the hash value:
a.       If it matches we are good to use the file
b.      If it doesn’t matches then we’ll delete this file and will go back to Step 2

Code for the solution
  1. Embedding file to the assembly : Add a “Resources” folder to your project. (optional – we’ll use this while retrieving file). Add the file Certificate.cer file to that folder and in the properties window of that file set the “Build Action” to “Embedded Resource".
  2. To retrieve and use this file use the following code :

  
namespace DefaultNamespace.FileHelper
{
    using System;
    using System.Configuration;
    using System.Diagnostics;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Text;

    /// The Certificate File Helper Class
    public class CertificateFileHelper
    {
        /// 
        /// For entry in assembly
        /// 
        private static Assembly _entryAssembly;

        /// 
        /// Syncronization Root
        /// 
        private static object _syncRoot = new object();

        /// 
        /// Hash of the help file
        /// 
        private static string _hashCertificate;

        /// 
        /// Gets the Certificate File Resource Namespace
        /// 
        public const string CertificateFileResourceNamespace = ".Resources.CertificateFile.cer";

        /// 
        /// Gets the location of the Certificate file.
        /// 
        public const string CertificateFileLocation = @"Resources\CertificateFile.cer";

        /// 
        /// Get or Set Entry in Assembly
        /// 
        private static Assembly EntryAssembly
        {
            get
            {
                lock (_syncRoot)
                {
                    if (null == _entryAssembly)
                    {
                        _entryAssembly = Assembly.GetEntryAssembly();
                    }

                    // In a automated test scenario the Entry Assembly comes back null so grab yourself
                    if (null == _entryAssembly)
                    {
                        _entryAssembly = Assembly.GetExecutingAssembly();
                    }

                    return _entryAssembly;
                }
            }
            set
            {
                lock (_syncRoot)
                {
                    _entryAssembly = value;
                }
            }
        }

        /// 
        /// Checks if the digital signature on config are valid or not
        /// 
        /// Returns true if signatures are valid else returns false
        public static void DoWorkUsingCertificateFile()
        {
            // Your Code
            // Your Code
            // Your Code

            // Gets the cerficate file
            string file = GetCertificateFile();

            // Your Code
            // Your Code
            // Your Code
        }

        /// 
        /// Writes the cetificate file to disk if the file is not present.
        /// 
        /// Path at which file is written
        private static string GetCertificateFile()
        {
            // Certificate file location
            var certificateFile = string.Format(
                                    CultureInfo.CurrentCulture,
                                    "{0}\\{1}",
                                    Path.GetDirectoryName(EntryAssembly.Location),
                                    CertificateFileLocation);

            // Checks if certificate file already exists
            if (File.Exists(certificateFile))
            {
                // Returns the certificate file path if the hash file is not tampered
                if (!string.IsNullOrEmpty(_hashCertificate) && GetMD5Hash(GetBytesFromFile(certificateFile)).Equals(_hashCertificate))
                {
                    return certificateFile;
                }

                // Delete the file if the file is tampered
                File.Delete(certificateFile);
            }

            // Getting the default namespace
            // Common string across al the types that assembly has
            string defaultNamespace = EntryAssembly.GetTypes().Aggregate(
                                                                    string.Empty,
                                                                    (current, type) => string.IsNullOrEmpty(current) ? type.Namespace : GetCommonString(current, type.Namespace));

            // Getting the file stream embedded in the assembly using its resource information
            var certificateFileStream = EntryAssembly.GetManifestResourceStream(defaultNamespace + CertificateFileResourceNamespace);

            // Create a FileStream object to write a stream to a file
            using (FileStream fileStream = File.Create(certificateFile, (int)certificateFileStream.Length))
            {
                // Fill the bytes[] array with the stream data
                byte[] bytesInStream = new byte[certificateFileStream.Length];
                certificateFileStream.Read(bytesInStream, 0, bytesInStream.Length);

                // Storing the hash of the file
                _hashCertificate = GetMD5Hash(bytesInStream);

                // Use FileStream object to write to the specified file
                fileStream.Write(bytesInStream, 0, bytesInStream.Length);
            }

            return certificateFile;
        }


        /// 
        /// Gets the MD5 hash of the file.
        /// 
        /// The input bytes.</param>
        /// Hexadecimal hash string
        private static string GetMD5Hash(byte[] inputBytes)
        {
            var hashString = new StringBuilder();
            using (var cryptoServiceProvider = new MD5CryptoServiceProvider())
            {
                byte[] hash = cryptoServiceProvider.ComputeHash(inputBytes);

                foreach (byte b in hash)
                {
                    hashString.Append(b.ToString("x2").ToLower());
                }
            }
            return hashString.ToString();
        }


        /// 
        /// Gets the common string. (We are using this method for getting the default namespace)
        /// 
        /// The first string.</param>
        /// The second string.</param>
        /// common string
        private static string GetCommonString(string firstString, string secondString)
        {
            string commonString = string.Empty;
            int shortStringLength = firstString.Length < secondString.Length ? firstString.Length : secondString.Length;
            for (int i = 0; i < shortStringLength; i++)
            {
                if (!firstString[i].Equals(secondString[i]))
                {
                    break;
                }
                commonString = commonString + firstString[i];
            }

            // Removing trailing periods
            commonString = commonString.TrimEnd('.');

            return commonString;
        }

        /// 
        /// Gets the bytes from file.
        /// 
        /// The full file path.</param>
        /// File read in byte array
        private static byte[] GetBytesFromFile(string fullFilePath)
        {
            byte[] bytes;
            // this method is limited to 2^32 byte files (4.2 GB)
            using (FileStream fileStream = File.OpenRead(fullFilePath))
            {
                bytes = new byte[fileStream.Length];
                fileStream.Read(bytes, 0, Convert.ToInt32(fileStream.Length));
            }
            return bytes;
        }
    }
}