SMS and email Two-Factor Authentication in ASP.NET MVC 5

Create an ASP.NET  MVC app

Start by installing and running Visual Studio Express 2013 for Web or  Visual Studio 2013 .  Install Visual Studio 2013 Update 3 or higher.

Warning: You should complete Create a secure ASP.NET MVC 5 web app with log in, email confirmation and password reset before proceeding. You must install Visual Studio 2013 Update 3 or higher to complete this tutorial.
  1. Create a new ASP.NET Web project and select the MVC template. Web Forms also supports ASP.NET Identity, so you could follow similar steps in a web forms app.
  2. Leave the default authentication as Individual User Accounts. If you’d like to host the app in Azure, leave the check box checked. Later in the tutorial we will deploy to Azure. You can open an Azure account for free .
  3. Set the project to use SSL .

Set up SMS for Two-factor authentication

This tutorial provides instructions for using either Twilio or ASPSMS but you can use any other SMS provider.

  1. Creating a User Account with an SMS provider

    Create a Twilio or an ASPSMS account.

  2. Installing additional packages or adding service references

    In the Package Manager Console, enter the following command:
    Install-Package Twilio

    The following service reference needs to be added:



  3. Figuring out SMS Provider User credentials

    From the Dashboard tab of your Twilio account, copy the Account SID and Auth token.

    From your account settings, navigate to Userkey and copy it together with your self-defined Password.

    We will later store these values in the web.config file within the keys "SMSAccountIdentification" and"SMSAccountPassword".

  4. Specifying SenderID / Originator

    From the Numbers tab, copy your Twilio phone number.

    Within the Unlock Originators Menu, unlock one or more Originators or choose an alphanumeric Originator (Not supported by all networks).

    We will later store this value in the web.config file within the key "SMSAccountFrom".

  5. Transferring SMS provider credentials into app

    Make the credentials and sender phone number available to the app. To keep things simple we will store these values in the web.config file. When we deploy to Azure, we can store the values securely in the app settingssection on the web site configure tab.

          <add key="webpages:Version" value="" />
          <!-- Markup removed for clarity. -->
          <!-- SendGrid-->
          <add key="mailAccount" value="account" />
          <add key="mailPassword" value="password" />
          <add key="SMSAccountIdentification" value="My Identification" />
          <add key="SMSAccountPassword" value="My Password" />
          <add key="SMSAccountFrom" value="+12065551234" />
    Security Note: Never store sensitive data in your source code. The account and credentials are added to the code above to keep the sample simple. See Best practices for deploying passwords and other sensitive data to ASP.NET and Azure .
  6. Implementation of data transfer to SMS provider

    Configure the SmsService class in the App_Start\IdentityConfig.cs file.

    Depending on the used SMS provider activate either the Twilio or the ASPSMS section:

    public class SmsService : IIdentityMessageService
        public Task SendAsync(IdentityMessage message)
            // Twilio Begin
            // var Twilio = new TwilioRestClient(
            //   System.Configuration.ConfigurationManager.AppSettings["SMSAccountIdentification"],
            //   System.Configuration.ConfigurationManager.AppSettings["SMSAccountPassword"]);
            // var result = Twilio.SendMessage(
            //   System.Configuration.ConfigurationManager.AppSettings["SMSAccountFrom"],
            //   message.Destination, message.Body
            // );
            // Status is one of Queued, Sending, Sent, Failed or null if the number is not valid
            // Trace.TraceInformation(result.Status);
            // Twilio doesn't currently have an async API, so return success.
            // return Task.FromResult(0);
            // Twilio End
            // ASPSMS Begin 
            // var soapSms = new MvcPWx.ASPSMSX2.ASPSMSX2SoapClient("ASPSMSX2Soap");
            // soapSms.SendSimpleTextSMS(
            //   System.Configuration.ConfigurationManager.AppSettings["SMSAccountIdentification"],
            //   System.Configuration.ConfigurationManager.AppSettings["SMSAccountPassword"],
            //   message.Destination,
            //   System.Configuration.ConfigurationManager.AppSettings["SMSAccountFrom"],
            //   message.Body);
            // soapSms.Close();
            // return Task.FromResult(0);
            // ASPSMS End
  7. Update the Views\Manage\Index.cshtml Razor view: (note: don’t just remove the comments in the exiting code, use the code below.)
    @model MvcPWy.Models.IndexViewModel
       ViewBag.Title = "Manage";
    <p class="text-success">@ViewBag.StatusMessage</p>

    Change your account settings

    [ @if (Model.HasPassword) { @Html.ActionLink("Change your password", "ChangePassword") } else { @Html.ActionLink("Create", "SetPassword") } ]
    External Logins:
    @Model.Logins.Count [ @Html.ActionLink("Manage", "ManageLogins") ]
    Phone Number:
    @(Model.PhoneNumber ?? "None") [ @if (Model.PhoneNumber != null) { @Html.ActionLink("Change", "AddPhoneNumber") @:  |  @Html.ActionLink("Remove", "RemovePhoneNumber") } else { @Html.ActionLink("Add", "AddPhoneNumber") } ]
    Two-Factor Authentication:
    @if (Model.TwoFactor) { using (Html.BeginForm("DisableTwoFactorAuthentication", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { @Html.AntiForgeryToken() Enabled type="submit" value="Disable" class="btn btn-link" /> } } else { using (Html.BeginForm("EnableTwoFactorAuthentication", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { @Html.AntiForgeryToken() Disabled type="submit" value="Enable" class="btn btn-link" /> } }
  8. Verify the EnableTwoFactorAuthentication and DisableTwoFactorAuthentication action methods in the ManageController have the [ValidateAntiForgeryToken] attribute:
    // POST: /Manage/EnableTwoFactorAuthentication
    public async Task<ActionResult> EnableTwoFactorAuthentication()
        await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), true);
        var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
        if (user != null)
            await SignInAsync(user, isPersistent: false);
        return RedirectToAction("Index", "Manage");
    // POST: /Manage/DisableTwoFactorAuthentication
    [HttpPost, ValidateAntiForgeryToken]
    public async Task<ActionResult> DisableTwoFactorAuthentication()
        await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), false);
        var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
        if (user != null)
            await SignInAsync(user, isPersistent: false);
        return RedirectToAction("Index", "Manage");
  9. Run the app and log in with the account you previously registered.
  10. Click on your User ID, which activates the Index action method in Manage controller.
  11. Click Add.
  12. The AddPhoneNumber action method displays a dialog box to enter a phone number that can receive SMS messages.
    // GET: /Account/AddPhoneNumber
    public ActionResult AddPhoneNumber()
       return View();

  13. In a few seconds you will get a text message with the verification code. Enter it and press Submit.
  14. The Manage view shows your phone number was added.

Enable two-factor authentication

In the template generated app, you need to use the UI to enable two-factor authentication (2FA). To enable 2FA, click on your user ID (email alias) in the navigation bar.

Click on enable 2FA.

Log out, then log back in. If you’ve enabled email (see my previous tutorial), you can select the SMS or email for 2FA.

The Verify Code page is displayed where you can enter the code (from SMS or email).

Clicking on the Remember this browser check box will exempt you from needing to use 2FA to log in when using the browser and device where you checked the box. As long as malicious users can’t gain access to your device, enabling 2FA and clicking on the Remember this browser will provide you with convenient one step password access, while still retaining strong 2FA protection for all access from non-trusted devices. You can do this on any private device you regularly use.



ID-Less URL Structure Demystified – How Does to Resolve ID-Less URLs?

I believe many of you nopCommerce pro users and developers are aware that nopCommerce 2.70 and 2.80 have employed a cleaner URL compared to the previous versions. From URLs that are suffixed with ‘.aspx’ in versions 1.XX; to extentionless but rather verbous URLs in versions 2.65 and below, we have seen a lot of changes in the URL structure in nopCommerce. However, none of them are as mysterious as the URLs in 2.70 and 2.80. Why? Because nopCommerce seems to know the magic to convert from any arbitrary texts to integer IDs.

For example, the link for my NopLite – nopCommerce Responsive Theme is You don’t see ANY integer in the URL, but nopCommerce somehow knows how to map from the URL to the appropriate ID. On the other hand, the nopCommerce 2.65 URL for my NopLite theme would have been: Note the ‘7’ somewhere in between the URL, that’s the Integer Product ID.

So the question is, how does nopCommerce 2.70 and 2.80 know the ID without looking the ID?

The UrlRecord Database Table

Well, the information is actually stored in a database table called UrlRecord. The table stores the slugs of entities to be mapped. A slug is any URL friendly-text and must be unique per nopCommerce installation. And then there is the EntityId column, which actually maps back to the actual entity represented by the slug. Last but not least, the EntityName column tells nopCommerce the actual entity type (Category, Product, BlogPost and etc) that an EntityId represents.

The nopCommerce database table UrlRecord stores the information of URL Slugs

This table, although useful, is only one part of the equation. We have stored the information, then there must be a way to connect the dots to somehow retrieve the information from the database, and map it with the URLs. The next part of the “magic” lies in the code.

Connecting the Dots – GenericUrlRouteProvider, GenericPathRoute and GenericPathRouteExtensions

First of all, let’s open Nop.Web.Framework.Seo.GenericPathRoute.cs, and you’ll see something like below:

Code snippet from GenericPathRoute.cs showing how it retrives UrlRecord from the database

Basically what the GenericPathRoute class does is to retrieve the RouteData information from the HttpRequest, extract the slug, and compare it with the database record (remember our UrlRecord database table?). If it eventually finds any active exsting record, it then provides additional values to the RouteData (see figure below) such as the Controller, the Action and the ID. In short, GenericPathRoute.cs encapsulates the logic that glue together the three pieces: UrlRecord database table, the actual Controller & Action that is responsible for producing the HTML result, and any other parameters required for the Action to perform correctly.

Code snippet showing how GenericPathRoute.cs class adds the required RouteData

But we are still missing one thing – we need to actually tell MVC to map the ID-less URLs to our freshly baked GenericPathRoute class. In other words, we have to let MVC routing engine knows that: when there is any ID-less URL coming in, we’ll let GenericPathRoute to do the heavy lifting of determining which Controller and Action to call and with what parameters. The figure below shows the GenericUrlRouteProvider class (found inNop.Web.Infrastructure.GenericUrlRouteProvider.cs) doing exactly this job. See the lines around the MapGenericPathRoute() method. The MapGenericPathRoute() method can be found inNop.Web.Framework.Seo.GenericPathRouteExtensions.cs.

GenericUrlRouteProvider doing the mapping between ID-less URLs and GenericPathRoute class

Conclusion – There is Actually No Magic in nopCommerce ID-less URLs

Yeap, the whole architecture in nopCommerce ID-less URLs is pretty clever, but there is really no magic in it. To recap, here are what make up of the ID-less URLs architecture:

  • UrlRecord database table – to store the mapping between a slug and the actual entity
  • GenericPathRoute class – to map a slug with the actual entity with the help of UrlRecord, thereby providing the RouteData to MVC’s routing engine
  • GenericUrlRouteProvider class – to tell MVC’s routing engine to let GenericPathRoute class handle ID-less URLs

Hope this explains the issue! Have any other topics that you want explained? Let me know in the comments, or better yet, use the UserVoice feedback widget at the right side to tell me your ideas! 🙂


Reference :

Tutorial: Getting Started with SignalR and MVC 4 (C#)


This tutorial introduces you to real-time web application development with ASP.NET SignalR and ASP.NET MVC 4. The tutorial uses the same chat application code as the SignalR Getting Started tutorial, but shows how to add it to an MVC 4 application based on the Internet template.

In this topic you will learn the following SignalR development tasks:

  • Adding the SignalR library to an MVC 4 application.
  • Creating a hub class to push content to clients.
  • Using the SignalR jQuery library in a web page to send messages and display updates from the hub.

The following screen shot shows the completed chat application running in a browser.

Chat instances


Set up the Project


  • Visual Studio 2010 SP1, Visual Studio 2012, or Visual Studio 2012 Express. If you do not have Visual Studio, seeASP.NET Downloads to get the free Visual Studio 2012 Express Development Tool.
  • For Visual Studio 2010, install ASP.NET MVC 4.

This section shows how to create an ASP.NET MVC 4 application, add the SignalR library, and create the chat application.

    1. In Visual Studio create an ASP.NET MVC 4 application, name it SignalRChat, and click OK.

      Note: In VS 2010, select .NET Framework 4 in the Framework version dropdown control. SignalR code runs on .NET Framework versions 4 and 4.5.

      Create mvc web

    2. Select the Internet Application template, clear the option to Create a unit test project, and click OK.

      Create mvc internet site

    3. Open the Tools | Library Package Manager | Package Manager Console and run the following command. This step adds to the project a set of script files and assembly references that enable SignalR functionality.

      install-package Microsoft.AspNet.SignalR

    4. In Solution Explorer expand the Scripts folder. Note that script libraries for SignalR have been added to the project.

      Library references

    5. In Solution Explorer, right-click the project, select Add | New Folder, and add a new folder namedHubs.
    6. Right-click the Hubs folder, click Add | Class, and create a new C# class named ChatHub.cs. You will use this class as a SignalR server hub that sends messages to all clients.

Note: If you use Visual Studio 2012 and have installed the ASP.NET and Web Tools 2012.2 update, you can use the new SignalR item template to create the hub class. To do that, right-click the Hubs folder, click Add | New Item, select SignalR Hub Class, and name the class ChatHub.cs.

  1. Replace the code in the ChatHub class with the following code.
    using System;
    using System.Web;
    using Microsoft.AspNet.SignalR;
    namespace SignalRChat
        public class ChatHub : Hub
            public void Send(string name, string message)
                // Call the addNewMessageToPage method to update clients.
                Clients.All.addNewMessageToPage(name, message);
  2. Open the Global.asax file for the project, and add a call to the method RouteTable.Routes.MapHubs(); as the first line of code in the Application_Start method. This code registers the default route for SignalR hubs and must be called before you register any other routes. The completed Application_Start method looks like the following example.
    protected void Application_Start()
  3. Edit the HomeController class found in Controllers/HomeController.cs and add the following method to the class. This method returns the Chat view that you will create in a later step.
    public ActionResult Chat()
        return View();
  4. Right-click within the Chat method you just created, and click Add View to create a new view file.
  5. In the Add View dialog, make sure the check box is selected to Use a layout or master page (clear the other check boxes), and then click Add.

    Add a view

  6. Edit the new view file named Chat.cshtml. After the <h2> tag, paste the following <div> section and@section scripts code block into the page. This script enables the page to send chat messages and display messages from the server. The complete code for the chat view appears in the following code block.

    Important: When you add SignalR and other script libraries to your Visual Studio project, the Package Manager might install versions of the scripts that are more recent than the versions shown in this topic. Make sure that the script references in your code match the versions of the script libraries installed in your project.

        ViewBag.Title = "Chat";
    <div class="container">
        <input type="text" id="message" />
        <input type="button" id="sendmessage" value="Send" />
        <input type="hidden" id="displayname" />
        <ul id="discussion">
    </div>@section scripts {
        <!--Script references. -->
        <!--The jQuery library is required and is referenced by default in _Layout.cshtml. -->
        <!--Reference the SignalR library. -->
        <script src="~/Scripts/jquery.signalR-1.0.1.js"></script>
        <!--Reference the autogenerated SignalR hub script. -->
        <script src="~/signalr/hubs"></script>
        <!--SignalR script to update the chat page and send messages.--> 
            $(function () {
                // Reference the auto-generated proxy for the hub.  
                var chat = $.connection.chatHub;
                // Create a function that the hub can call back to display messages.
                chat.client.addNewMessageToPage = function (name, message) {
                    // Add the message to the page. 
                    $('#discussion').append('<li><strong>' + htmlEncode(name) 
                        + '</strong>: ' + htmlEncode(message) + '</li>');
                // Get the user name and store it to prepend to messages.
                $('#displayname').val(prompt('Enter your name:', ''));
                // Set initial focus to message input box.  
                // Start the connection.
                $.connection.hub.start().done(function () {
                    $('#sendmessage').click(function () {
                        // Call the Send method on the hub. 
                        chat.server.send($('#displayname').val(), $('#message').val());
                        // Clear text box and reset focus for next comment. 
            // This optional function html-encodes messages for display in the page.
            function htmlEncode(value) {
                var encodedValue = $('<div />').text(value).html();
                return encodedValue;
  7. Save All for the project.

Run the Sample

  1. Press F5 to run the project in debug mode.
  2. In the browser address line, append /home/chat to the URL of the default page for the project. The Chat page loads in a browser instance and prompts for a user name.

    Enter user name

  3. Enter a user name.
  4. Copy the URL from the address line of the browser and use it to open two more browser instances. In each browser instance, enter a unique user name.
  5. In each browser instance, add a comment and click Send. The comments should display in all browser instances.

    Note: This simple chat application does not maintain the discussion context on the server. The hub broadcasts comments to all current users. Users who join the chat later will see messages added from the time they join.

  6. The following screen shot shows the chat application running in a browser.

    Chat browsers

  7. In Solution Explorer, inspect the Script Documents node for the running application. This node is visible in debug mode if you are using Internet Explorer as your browser. There is a script file named hubs that the SignalR library dynamically generates at runtime. This file manages the communication between jQuery script and server-side code. If you use a browser other than Internet Explorer, you can also access the dynamic hubsfile by browsing to it directly, for example http://mywebsite/signalr/hubs.

    Generated hub script

Examine the Code

The SignalR chat application demonstrates two basic SignalR development tasks: creating a hub as the main coordination object on the server, and using the SignalR jQuery library to send and receive messages.

SignalR Hubs

In the code sample the ChatHub class derives from the Microsoft.AspNet.SignalR.Hub class. Deriving from theHub class is a useful way to build a SignalR application. You can create public methods on your hub class and then access those methods by calling them from jQuery scripts in a web page.

In the chat code, clients call the ChatHub.Send method to send a new message. The hub in turn sends the message to all clients by calling Clients.All.addNewMessageToPage.

The Send method demonstrates several hub concepts :

  • Declare public methods on a hub so that clients can call them.
  • Use the Microsoft.AspNet.SignalR.Hub.Clients property to access all clients connected to this hub.
  • Call a jQuery function on the client (such as the addNewMessageToPage function) to update clients.
    public class ChatHub : Hub
        public void Send(string name, string message)
            Clients.All.addNewMessageToPage(name, message);

SignalR and jQuery

The Chat.cshtml view file in the code sample shows how to use the SignalR jQuery library to communicate with a SignalR hub. The essential tasks in the code are creating a reference to the auto-generated proxy for the hub, declaring a function that the server can call to push content to clients, and starting a connection to send messages to the hub.

The following code declares a proxy for a hub.

var chat = $.connection.chatHub; 

Note: In jQuery the reference to the server class and its members is in camel case. The code sample references the C# ChatHub class in jQuery as chatHub. If you want to reference the ChatHub class in jQuery with conventional Pascal casing as you would in C#, edit the ChatHub.cs class file. Add a using statement to reference theMicrosoft.AspNet.SignalR.Hubs namespace. Then add the HubName attribute to the ChatHub class, for example[HubName("ChatHub")]. Finally, update your jQuery reference to the ChatHub class.

The following code shows how to create a callback function in the script. The hub class on the server calls this function to push content updates to each client. The optional call to the htmlEncode function shows a way to HTML encode the message content before displaying it in the page, as a way to prevent script injection.

chat.client.addNewMessageToPage = function (name, message) {
    // Add the message to the page. 
    $('#discussion').append('<li><strong>' + htmlEncode(name) 
        + '</strong>: ' + htmlEncode(message) + '</li>');

The following code shows how to open a connection with the hub. The code starts the connection and then passes it a function to handle the click event on the Send button in the Chat page.

Note: This approach ensures that the connection is established before the event handler executes.

$.connection.hub.start().done(function () {
    $('#sendmessage').click(function () {
        // Call the Send method on the hub. 
        chat.server.send($('#displayname').val(), $('#message').val());
        // Clear text box and reset focus for next comment. 

Next Steps

You learned that SignalR is a framework for building real-time web applications. You also learned several SignalR development tasks: how to add SignalR to an ASP.NET application, how to create a hub class, and how to send and receive messages from the hub.

You can make the sample application in this tutorial or other SignalR applications available over the Internet by deploying them to a hosting provider. Microsoft offers free web hosting for up to 10 web sites in a free Windows Azure trial account. For a walkthrough on how to deploy a simple SignalR application, see Publish the SignalR Getting Started Sample as a Windows Azure Web Site. For detailed information about how to deploy a Visual Studio web project to a Windows Azure Web Site, see Deploying an ASP.NET Application to a Windows Azure Web Site. (Note: The WebSocket transport is not currently supported for Windows Azure Web Sites. When WebSocket transport is not available, SignalR uses the other available transports as described in the Transports section of theIntroduction to SignalR topic.)

To learn more advanced SignalR developments concepts, visit the following sites for SignalR source code and resources :

Reference :

Access ODBC Driver 32bit in x64 bit version Window

That is so strange in Window architecture. As ODBC Drivers are in C:\Windows\SysWOW64\odbcad32.exe in Window x64 but x64 Application can not access to its drivers.

Any application develop based x64 bit version will got this error.

the strange is the connection pointing to 32bit driver version. In the 32 bit registry does not contain any driver path.

but it is exist in x64 path.



Creating platform specific apps

Most of the language compilers (like C#) now offer a /platform switch. By using this switch, developers can create binaries targeted for a specific platform type or binaries that are platform agnostic. There are four types of binaries that are emitted

· any cpu – platform agnostic

· x86 – 32-bit platform specific

· x64 – x64 platform specific

By default the compilers (like C#) emit anycpu binaries (also called portable assemblies) which are platform agnostic. In case the users want to create binaries specific to a platform, they can use the appropriate switch and be done.

Cross Compilation

The above concept of /platform switch enables cross compilation of binaries. Cross compilation means compiling binaries to a specific platform type (different from the current platform). This is mostly used in terms of compiling and creating 64-bit assemblies from a 32-bit compiler and vice versa. One point to note here is that cross compilation usually refers to compiling to different target types from the compilers shipped with the 64-bit Redist (WoW and 64-bit). The reason for this is that, while trying to compile for a 64-bit platform from a pure 32-bit machine, the 32-bit Redist would not have the components that are 64-bit specific. In such cases the compilation might go through with warning but execution might lead to runtime exceptions. Also, one should note that while cross compiling, users should stick to the platform architecture type of the machine, viz. x64 or IA. Assemblies for IA and x64 are specific to the platform architecture and cross compilation across architectures is not advised.


Using Delegates and Events to Communicate Between Forms


This article provides a simple example of using delegates and events to transfer data between Windows forms. The example provided contains three separate forms; the main form interacts with the other two forms by responding to events generated by instances of the other two forms.

In order to communicate between the forms, each of forms capable of generating an event contains declarations for a delegate and an event. A delegate may be thought of as a type safe function pointer and delegates are associated with methods that bear the same signature. An event is a device used to notify listening objects that something has happened; events are associated with a delegate when instantiated.

Through the use of delegates and events it is possible to communicate values between forms in a Win Forms application.

Figure 1. Using Delegates and Events to Communicate Between Forms


Continue reading

Encrypting and Decrypting a C# string

The .NET C# library provides all the basic elements for encrypting a string with a passphrase and decrypting it later. Doing this however requires a few steps in between. This post show a simple set of routines to help you do just that. We use the TripleDES encryption suite to do the actual encryption, with a little help from the MD5 hash sum generator.

The complete source code is listed below, but lets have a little look at how it works first.


The problem

I want to take a string, and then encrypt it using a password. The result should be a Base64 encoded string that I can store somewhere relatively safe.

01.// The message to encrypt.
02.string Msg = "This world is round, not flat, don't believe them!";
03.string Password = "secret";
05.string EncryptedString = EncryptString(Msg, Password);
06.string DecryptedString = DecryptString(EncryptedString, Password);
08.Console.WriteLine("Message: {0}",Msg);
09.Console.WriteLine("Password: {0}",Password);
10.Console.WriteLine("Encrypted string: {0}",EncryptedString);
11.Console.WriteLine("Decrypted string: {0}",DecryptedString);

In the EncryptString function we apply the TripleDES algorithm with a 128 bit key. But first we need to turn the above passphrase (’secret’) into a 128 bit key. One useful coincidence is that the MD5 hash algorithm accepts a set of bytes of any length and turns them into a 128 bit hash. So by running the password through the MD5 hashing algorithm we create our key.

1.// Step 1. We hash the passphrase using MD5
2.// We use the MD5 hash generator as the result is a 128 bit byte array
3.// which is a valid length for the TripleDES encoder we use below
5.MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
6.byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));

The TripleDES algorithm itself turns a byte array into an encrypted byte array. So we first need to convert our C# message string (which is Unicode encoded) into a byte array through the System.Text.UTF8Encoding encoder.

The key is used to initialize the TripleDES algorithm. In addition we need to specify that we will only encode something once (CipherMode.ECB) and because its unlikely that our source string fits into a single TripleDES block we need to specify how we want to pad any remaining bytes (PaddingMode.PKCS7).

1.// Step 2. Create a new TripleDESCryptoServiceProvider object
2.TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
4.// Step 3. Setup the encoder
5.TDESAlgorithm.Key = TDESKey;
6.TDESAlgorithm.Mode = CipherMode.ECB;
7.TDESAlgorithm.Padding = PaddingMode.PKCS7;

The encrypted byte array is finally converted into a Base64 encoded string for easy storage. The DecryptString function is very similar to the encryption function, except that it turns the Base64 encoded encrypted message back into the original UTF8 string.

Drawbacks to the above method

To keep the code above straightforward we made use of the fact that an MD5 hash is exactly 128 bits in length. The C# TripleDES code accepts three possible key lengths: 64 bit, 128 bit and 192 bit. Only 192 bit keys are truly TripleDES, the 128 bit key length we obtain from the MD5 hash is only sufficient for Double DES. According to Wikipedia, that would make its real key strength only equivalent to 80 bits.

The Source code

001.using System;
002.using System.Text;
003.using System.Security.Cryptography;
005.namespace EncryptStringSample
007.class MainClass
010.public static string EncryptString(string Message, string Passphrase)
012.byte[] Results;
013.System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
015.// Step 1. We hash the passphrase using MD5
016.// We use the MD5 hash generator as the result is a 128 bit byte array
017.// which is a valid length for the TripleDES encoder we use below
019.MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
020.byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));
022.// Step 2. Create a new TripleDESCryptoServiceProvider object
023.TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
025.// Step 3. Setup the encoder
026.TDESAlgorithm.Key = TDESKey;
027.TDESAlgorithm.Mode = CipherMode.ECB;
028.TDESAlgorithm.Padding = PaddingMode.PKCS7;
030.// Step 4. Convert the input string to a byte[]
031.byte[] DataToEncrypt = UTF8.GetBytes(Message);
033.// Step 5. Attempt to encrypt the string
036.ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
037.Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
041.// Clear the TripleDes and Hashprovider services of any sensitive information
046.// Step 6. Return the encrypted string as a base64 encoded string
047.return Convert.ToBase64String(Results);
050.public static string DecryptString(string Message, string Passphrase)
052.byte[] Results;
053.System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
055.// Step 1. We hash the passphrase using MD5
056.// We use the MD5 hash generator as the result is a 128 bit byte array
057.// which is a valid length for the TripleDES encoder we use below
059.MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
060.byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));
062.// Step 2. Create a new TripleDESCryptoServiceProvider object
063.TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
065.// Step 3. Setup the decoder
066.TDESAlgorithm.Key = TDESKey;
067.TDESAlgorithm.Mode = CipherMode.ECB;
068.TDESAlgorithm.Padding = PaddingMode.PKCS7;
070.// Step 4. Convert the input string to a byte[]
071.byte[] DataToDecrypt = Convert.FromBase64String(Message);
073.// Step 5. Attempt to decrypt the string
076.ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor();
077.Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length);
081.// Clear the TripleDes and Hashprovider services of any sensitive information
086.// Step 6. Return the decrypted string in UTF8 format
087.return UTF8.GetString( Results );
090.public static void Main(string[] args)
092.// The message to encrypt.
093.string Msg = "This world is round, not flat, don't believe them!";
094.string Password = "secret";
096.string EncryptedString = EncryptString(Msg, Password);
097.string DecryptedString = DecryptString(EncryptedString, Password);
099.Console.WriteLine("Message: {0}",Msg);
100.Console.WriteLine("Password: {0}",Password);
101.Console.WriteLine("Encrypted string: {0}",EncryptedString);
102.Console.WriteLine("Decrypted string: {0}",DecryptedString);