Thursday, December 17, 2009

Microsoft Identity Model in Web Farm

Microsoft Identity Model for claims based authentication uses SessionSecurityTokenHandler to create cookie. This cookie is encrypted using DPAPI. This will not work if you are going to deploy your applications in Webfarm or in general Microsoft Azure platform. To support Web Farm deployment we need to remove the default Cookie Transform used by the Session Security Handler and then add our own customized cookie transform.

We need to provide two cookie transforms

  1. For encryption based upon the machine key settings
  2. HMAC-SHA1 cookie transform for tamper proofing of the cookie.

In next few days, my team will be providing both the cookie transforms and sample code to demonstrate this.

Thanks,

Ashwani

Cryptography Library in .Net

During the development of Application framework, I created a library that would help to perform cryptography functions in the application. Here I am providing brief overview of cryptography and code that performs cryptography functions.

Encryption is a technique by which plain text information is converted in data stream (cipher text) which looks like meaningless.
Decryption is the process of converting the cipher text (encrypted data stream) to readable plain text.

.Net Cryptography supports symmetric encryption, asymmetric encryption and hashing to convert plain text into cipher text.


Symmetric Encryption

These cryptography algorithms use the same key for encryption and decryption. Algorithms that operate on 1 bit or 1 byte of plaintext at a time are called stream ciphers whereas
algorithms that operate on blocks of bits at a time are called block ciphers.

Where to use Symmetric Encryption
These algorithms should be used to encrypt the messages within one application because same key is used for encryption and decryption. Using symmetric encryption with third party applications is not recommended as you need to share the encryption key.

Important Symmetric Encryption Algorithms

Data Encryption Standard:

DES is a block cipher which uses 56-bit fixed length key to generate cipher text. Any 56 bit value can be a key.
Due to short length of the key this algorithm is vulnerable to brute-force attack.

TripleDES:


Triple DES improves the DES algorithm by applying DES three times using three different keys by which effective key length becomes 168 bits.

Advanced Encryption Standard (AES) aka Rijndael:


This is block cipher and supports key lengths of 128, 192 and 256 bits. It is recommended to uses 256 bits key.

What is Initialization Vector
To ensure that encryption of the same string and with the same key is different everytime we perform the encryption, the output (cipher block) of previous block is appended to the next block to perform the encryption. But for the first block initialization vector is used. It is important to use the random IV everytime we perform the encryption operation.


 

Hashing

This is one way hash function which takes the variable length string and converts that to the fixed length binary sequence. Using the hash value you can't retrieve the original value. This is only one way conversion; however you can always compare the two hash values to check whether those are same or not.

Where to use Hashing
Hashing should be used where you need to protect the information and doesnot want the original text. For example: User's Passowrd.
User's Password can be hashed and stored in the database and during the login calculate the hash of the password entered by the user. We compare the hash value just calculated with the value stored in the database, if both matches that means user has entered the valid password.

Hashing Algorithms

MD5:
This algorithm produces 128 bit hash value.

SHA1:
This algorithm produces 160 bit hash value. Always use SHA because it produces larger hash value as compared to MD5.

Salt Value
One problem with hashing is that if two user's selected the same password then the hash value will also be same. One way to ensure that the hash of two same strings will never be same is to add the salt value (unique value) to the original text before hashing. The salt value can be generated using RNGCryptoServiceProvider. You require this salt value during comparison. You have two options either to store the salt as the part of the hash value so that later it can be extracted from the hash value or store the salt value as separate. The attached code appends the salt value as part of the hash itself.


 

Difference between Hashing and HMAC

During development of Security Framework of Rest Services, I figured out that why hashing alone is not sufficient and we need to perform the HMAC. Here is the difference between two.

Hashing: It produces standard 20 byte fixed length hash (using SHA1). Now if we send the request to the service along with the hash value of the Request Parameters for tamper proofing, the service will also compute the hash value of all the request parameters to check whether the information has been tampered or not. Things look fine but actually here is one problem. Some Attacker changes the request parameters, recalculates the hash of the changed request parameters and then sends the request using the new request parameters and new hash value. Now service recalculates the hash value from the request parameters and found the hash value to be correct (because the hash value is itself replaced with the new one.). So hashing in this scenario will not work for tamper proofing.
Hashing should be used only within one layer of the application or between layers where communication between the layers is encrypted and highly secured like storing password because the hash is calculated in the business layer and stored in the database. The communication between the business layer and database is generally behind the firewall and secured.

So in the above scenario, we have to use HMAC in which a secret key is shared between the two parties and using that secret key the HMAC is calculated. What HMAC does is, it takes the hash of the shared key + message, prepends the key to that hash, and then re-hashes the result. This makes it cryptographically sound and thus used for digital signing.

HMAC = hash (sharedkey + hash (sharedkey + message))

Forms Authentication Ticket, Roles Cookie uses HMac for tamper proofing.


 

Performing Encryption/Digital Signing in ASP.Net

.Net has machine key settings in the machine.config file by which forms authentication ticket, roles cookie are encrypted and signed.

The default values for the machinekey are

<pages enableViewStateMac="true" viewStateEncryptionMode="Auto" ... />


 

<machineKey validationKey="AutoGenerate,IsolateApps"

decryptionKey="AutoGenerate,IsolateApps"

validation="SHA1" decryption="Auto" />


 

When you configure ViewState, the <pages> element is used in conjunction with the <machineKey> element.

The <machineKey> attributes are

  • validationKey: This key specifies the HMAC key which is used for making viewstate tamper proof, signing the forms authentication ticket, signing Roles cookie.
  • decryptionKey: This specifies the key that will be used to encrypt or decrypt the data. This key is used to encrypt data of forms authentication ticket, roles cookie.
  • decryption: This specifies the symmetric algorithm that will be used for encryption and decryption. The values can be AES, 3DES, DES
  • validation: This specifies the algorithm used to generate HMAC for making viewstate tamper proof, signing forms authentication ticket. The various values can be SHA1, MD5, AES and 3DES. The values AES and 3DES are used in ASP.Net 1.1 because the decryption was only introduced in 2.0

Always use SHA1 because this produces larger hash as compared to MD5.

Forms authentication defaults to SHA1 for tamper proofing (if <forms protection="validation" or "All").
When <forms protection="All"> or <forms protection = "Encryption">, then forms authentication hashes the forms authentication ticket by using either MD5 or HMACSHA1


 

Performing Cryptography Operations:

In every application there are scenarios where we need to encrypt/ decrypt, hash or digital sign the information. The attached code provides the library for performing these operations. Brief overview of the library is explained below:

As mentioned Microsoft uses machineKey to encrypt/ decrypt, digitally sign the authentication cookie, roles cookie so it is better to use same keys for crypto operation which we perform in the application.

The first step would be to generate the decryption and validation keys. We should keep in mind that our applications will be deployed in web farm environment or not. It is always better to specify the specific values of decryption and validation keys so that in future web farm deployment will be easier. Attached code contains the Console Project which describes the way to generate decryption and validation keys.

MachineKey Wrapper: Code contains machine Key wrapper that reads machineKey settings from the config file.

Encryption/ Decryption: The code contains various operations for performing encryption and decryption including encryption and decryption of XML documents/ elements. These methods use decryption and decryptionKey element of the machineKey settings.

Hashing: Code contains methods for creating the hash and then comparing the hash value. Salt is randomly generated and stored as part of hash value. These methods use only the validation attribute of machineKey settings.

Note: The validationKey attribute is used is not used for hashing, this value is used for HMAC which is different from hashing as explained above.

Digital Signing (HMAC): Code contains various methods for creating and comparing the signature. The validation Key mentioned in the machineKey settings of web.config file is the secret key which HMAC uses for generating signature.

Cryptography Library in .Net

References:

http://msdn.microsoft.com/en-us/library/ms998288.aspx

http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.aspx

http://www.4guysfromrolla.com/webtech/LearnMore/Security.asp

http://msdn.microsoft.com/en-us/library/5e9ft273%28VS.100%29.aspx

http://dev.ionous.net/2009/03/hmac-vs-raw-sha-1.html

Friday, July 3, 2009

WCF Client Authentication using X509 certificates on SSL

In one of my project; there is a requirement

a. Web Services (WCF) Clients should be authenticated by X509 certificates.

b. Clients should validate the web services using X509 certificate (using SSL).

c. All these services should be built using basicHttpBinding and to be consumed by .Net 2.0 clients.

I am describing here the complete solution to achieve this and the settings to be done in IIS.

SSL Layer: In order to run web services on SSL; you need to get certificate from the certificate authority like VeriSign; however in development environment sometimes you donot have certificate from valid Authority and need to generate self signed certificate. Microsoft provides a utility to generate self signed certificates.

makecert.exe -r -pe -a sha1 -n CN=”Ent.com” -sr LocalMachine -ss My -sky exchange -b 01/01/2000 -e 01/01/2036 Ent.cer

The above command creates the self signed certificates and places this certificate in the Local Computer Account under personal store.

The configuration in IIS is simple as shown below:

a. Right Click WebSite (say Ent.com, where your WCF services are hosted). Go to properties and then go to Directory Security tab.


b. Click Server Certificate button. This will open the wizard to install certificate. Click “Next” and you will see the following screen. Select option “Assign an existing certificate” and click “Next”.

c. Now select the certificate you created “Ent.com” and click “Next”.


  1. Select the port number (for SSL default is 443) and click finish.
  2. Now if you want to enable 128 bit encryption you can edit the certificate details by clicking “Edit” button on the Directory Security tab and click the checkbox “Require 128-bit encryption”.


Some configuration changes need to be done in web.config file (WCF hosting configuration file). These configuration settings are described at the end of article.


That’ it you are done with installing SSL.

Now you can Add Web Reference in your .Net 2.0 project. However when you try to access the Web Service from your client application you will get the following error:


“The underlying connection was closed: Could not establish trust relationship for the
SSL/TLS secure channel.”


This exception is raised by client during SSL handshake because Server certificate is not issued b
y valid Authority.

In order to fix this problem, you need to tell client that it allows your certificate. The following code needs to be written and called before calling the service method.

protected void button1_Click(object sender, EventArgs e)

{

Testing.Service service1 = new Testing.Service();

ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(customCertificateValidation);

string data = service1.GetData(5, true);

label1.Text = data;

}

private bool customCertificateValidation(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error)

{

//analyze the certificate and then return true.

return true;

}

The custom certificate validation method allows clients applications to decide which server certificates they can trust.

Note: Allowing self signed certificates is not recommended in Production environment.



X509 Client Certificate Authentication:

The next thing to do is client authentication using X509 certificates. In order to do this you need to change configuration in IIS and also in web.config file.

IIS settings

a. Right Click web site (say Ent.com). Go to properties and then go to Directory Security tab.


b. Click Edit button and then on “Client Certificate” Section select the option “Require client certificates”


Client Side Changes

Now when you call the web service you need to provide client Certificate. Here is the code:

protected void button1_Click(object sender, EventArgs e)

{

Testing.Service service1 = new Testing.Service();

//As an example loading certificate from file system.

X509Certificate cert = X509Certificate2.CreateFromCertFile(@"C:\Test1.cer");

service1.ClientCertificates.Add(cert); //adding cleint certificate.

ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(customXertificateValidation);

string data = service1.GetData(5, true);

label1.Text = data;

}

private bool customXertificateValidation(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error)

{

//analyze the certificate and then return true.

return true;

}

The “Test1” certificate used here is self signed certificate. In production environment this certificate should be issued by valid authority. However to fix the problem in development environment you need to add the certificate in the “Trusted Root Certification Authorities” on you WCF hosting machine.


Web.config changes:

The complete config file is:

<system.serviceModel>

<services>

<service name="Service" behaviorConfiguration="ServiceBehavior">

<endpoint address="https://Ent.com/Services/Service.svc" binding="basicHttpBinding" contract="IService" bindingConfiguration="Binding">

<identity>

<dns value="localhost"/>

identity>

endpoint>

service>

services>

<behaviors>

<serviceBehaviors>

<behavior name="ServiceBehavior">

<serviceMetadata httpsGetEnabled="true"/>

<serviceDebug includeExceptionDetailInFaults="true"/>

behavior>

serviceBehaviors>

behaviors>

<bindings>

<basicHttpBinding>

<binding name="Binding">

<security mode="Transport">

<transport clientCredentialType="Certificate"/>

security>

binding>

basicHttpBinding>

bindings>

system.serviceModel>


Description:

  • In order to use SSL you need to tell that you are using transport layer security using the tag.

<security mode="Transport">security>

  • In order to use client certificates for authentication you need to specify ClientCertificateType as Certificate

    <security mode="Transport">
    <transport clientCredentialType="Certificate"/>

    <security/>

However after changes these settings when you try to run the application you will get strange error saying:

Client found response content type of '', but expected 'text/xml'.
The request failed with an empty response.

In order to fix this error you need to comment the following line in web.config file

< ! - - < address="mex" binding="mexHttpsBinding" contract="IMetadataExchange">- - >

That’s all. Now you can use WCF services from .Net 2.0 clients on SSL and using client certificate authentication.


The complete Code can be downloaded from here

You can generate the certificate using Microsoft tool as described above.


Ashwani Kumar

Solutions Architect

Globallogic Inc.

Thursday, April 9, 2009

Custom Code for SAML 1.1 digital verification

Attached is the custom code for Digital verification of SAML 1.1 Token

Source Code

Saturday, March 7, 2009

Custom Forms Authentication in ASP.Net and Classic ASP

Custom Implementation of Forms Authentication

Classic ASP developers often had to "roll their own" authentication scheme, however, in ASP.NET much of the grunt work has been taken out. In this blog I will be explaining the technology behind the forms authentication and you can write your own forms authentication in Classic ASP or in any other language. Recently I have implemented Forms Authentication in Classic ASP.

Security Overview

One of the new features of ASP.NET is Forms Authentication. Like in classic ASP, where custom database authentication occurred through the user entering his or her login credentials via an HTML form, ASP.NET Forms Authentication works similarly. However, using this neat feature, many of the mundane tasks and code that you were required to write in classic ASP are handled for you automagically.

When an unauthenticated user attempts to access a Forms Authentication protected web site the following process occurs:

1) The Forms Authentication HttpModule redirects the user to the logon page

2) User enter user name and password

3) A FormsAuthenticationTicket is constructed based on configuration information

4) The FormsAuthentication.Encrypt() method is called and returns a hex string containing the user’s ticket.

5) The encrypted ticket string is then placed into a cookie and added to the user’s cookie collection.

What is forms authentication ticket and forms authentication cookie? How are they related?

Forms authentication cookie is nothing but the container for forms authentication ticket. The ticket is passed as the value of the forms authentication cookie with each request and is used by forms authentication, on the server, to identify an authenticated user.

However, if we choose to use cookieless forms authentication, the ticket will be passed in the URL in an encrypted format. Cookieless forms authentication is used because sometimes the client browsers block cookies.

Forms Authentication Ticket

The forms authentication ticket is used to tell the ASP.NET application who you are. Thus, ticket is building block of Forms Authentication's security.


The ticket is encrypted and signed using the configuration element of the server's Machine.config file. ASP.NET 2.0 uses the decryptionKey and the new decryption attribute of the element to encrypt forms authentication tickets. The decryption attribute lets you specify the encryption algorithm to use. ASP.NET 1.1 and 1.0 use 3DES encryption, which is not configurable. Tampering with the ticket value is determined by a failure to decrypt the ticket on the server. As a result, the user will be redirected to the logon page.

If the application is deployed in a Web farm, you must make sure that the configuration files on each server share the same value for the validationKey and decryptionKey attributes in the tag, which are used for hashing and decryption of the ticket respectively. You must do this because you cannot guarantee which server will handle successive requests.

Generating Ticket in custom Forms Authentication Process

In the attached code FormsAuthentication.Encrypt() method of FormsAuthentication class is used to convert the ticket into a binary blob (byte array), digitally sign it, encrypt it, and format it in such a way that it can easily be place into a cookie.

In Microsoft’s implementation the conversion of the ticket into a binary blob is “black boxed” in a method named “CookieAuthContructTicket” (located in the native dll “webengine.dll”).

The ticket blob is constructed of the formatted property values defined in the FormsAuthencticationTicket class.

FormsAuthenticationTicket Properties:

Property Type Data

Name String Username

UserData String Any extra user information

CookiePath String The path the cookie is valid for ie. /AppPath

Expriation DateTime The time at which the ticket is invalid

IssueDate DateTime The time at which the ticket was issued

IsPersistent bool Indicates if the ticket is a persistent ticket

Version int The ticket version

These properties are formatted and combined into a binary blob.

1) Each string value is converted to a byte array (represented as a Unicode string).

2) Each DateTime value is converted into the equivalent “FileTime” (represented as a long value) and converted to a byte array.

3) IsPersistent and Version are cast to their equivalent byte representation

After these properties are converted to their byte array equivalents, the final ticket blob is constructed as described below.

1) Eight random bytes are generated and become the first 8 bytes of the final blob. This is done to ensure each encrypted ticket will differ even if the data is the same.

2) The “Version” byte is added at the 8th position of the blob.

3) Followed by the "Name" bytes

4) Followed by a 2 byte delimiter (both bytes are 0’s)

5) Followed by the "IssueDate" bytes

6) Followed by the "IsPersistent" byte

7) Followed by the “Expires” bytes

8) Followed by the “UserData” bytes

9) Another two byte delimiter is placed directly after the “UserData” bytes

10) Followed by the “CookiePath” bytes

11) Last but not least a final delimiter (another 0) is appended

Below is a detailed diagram of the final ticket blob….

Digitally sign the ticket:

After the ticket blob has been constructed it must be digitally signed to ensure the information is not tampered with. The digital signature is an HMAC (Hashed Message Authentication Code) hash of the ticket blob. Depending on the configuration either MD5 or SHA1 is used for the HMAC. In managed code these classes are implemented as HMACMD5 and HMACSHA1. The digital signature is a 20 byte hash of the data. This hash is appended to the end of ticket blob.

Encrypting the ticket and signature:

At this point in the process we have a binary blob (byte array) containing all of the ticket information as well as the signature of this data. Before transporting this information it must be encrypted. Depending on the configuration the information is either encrypted using AES (implemented as RijndaelManaged in managed code) or 3Des (implemented as TripleDesCryptoServiceProvider in managed code).

Formatting the encrypted ticket and signature:

Given that the encrypted ticket will need to be inserted into a cookie, the final step is to create a string from the data blob. There are a couple of choices on how you can go about doing this. Many people convert byte arrays to Base64 strings and transport them that way. Microsoft went another, equally valid route, and chose to encode the data as a hex string.

Stuffing the ticket into a Cookie:

With our hex string in hand we are set to complete the process. The final step is to simply place the hex string into a cookie and send it off to the user’s browser.

Writing HTTP Module

At this point the user has been given the keys to the website. Each time the user attempts to visit a site HttpModule intercepts the request, retrieves the cookie, grabs the ticket from the cookie, and does the reverse of whole process described above. If the decryption succeeds (which will only happen if the same key is used for decryption) and the signature is valid then the user is given access to the page or site.

Sliding Expiration

Let us take an example: If the logon page is accessed at 5:00 00:00:00 PM, it should expire at 5:10 00:00:00 PM if the timeout attribute is 10 and the slidingExpiration attribute is set to TRUE. Now, if any Web page is browsed again at 5:05 00:00:00 PM, the cookies and ticket time-out period will be reset to 5:15 00:00:00 PM.


If the Web page is accessed before half of the expiration time passes, the ticket expiration time will not be reset. For example, if any Web page is accessed again at 5:04 00:00:00 PM, the cookies and ticket timeout period will not be reset. It’s the responsibility of the HTTP Module to reissue the ticket when sliding expiration is set.

Source Code: Download

The code consist of

  • Library project that contains the classes to implement the forms authentication. The library project also contains the HTTP Module which intercepts the request and validate the token or reissue the token in case of sliding expiration.

  • Web Project which uses the custom build forms authentication.

Read other related topics

Forms Authentication in WebFarm

Generating decryption and validation key.