Sample code for Encryption\Decryption of Password (strings) in C#


Hi,

Just sharing the helper classes that we have used in our project.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

namespace WindowsFormsApplication5
{
 public class SaltedHash
 {
 #region Fields

/// <summary>
 /// Delimiter character
 /// </summary>
 private string delimiter = " ";

/// <summary>
 /// Hash Provider
 /// </summary>
 private HashAlgorithm hashProvider;

/// <summary>
 /// Salth length
 /// </summary>
 private int salthLength;

#endregion Fields

#region Constructors

/// <summary>
 /// Initializes a new instance of the SaltedHash class.
 /// </summary>
 /// <param name="hashAlgorithm">A <see cref="HashAlgorithm"/> HashAlgorihm which is derived from HashAlgorithm. C# provides
 /// the following classes: SHA1Managed,SHA256Managed, SHA384Managed, SHA512Managed and MD5CryptoServiceProvider</param>
 /// <param name="theSaltLength">Length in bytes</param>
 public SaltedHash(HashAlgorithm hashAlgorithm, int theSaltLength)
 {
 this.hashProvider = hashAlgorithm;
 this.salthLength = theSaltLength;
 }

/// <summary>
 /// Initializes a new instance of the SaltedHash class.
 /// </summary>
 public SaltedHash()
 : this(new SHA256Managed(), 4)
 {
 }

#endregion Constructors

#region Methods

/// <summary>
 /// Gets the hashed string with salt
 /// </summary>
 /// <param name="data">The data to hash</param>
 /// <returns> The hashed string </returns>
 public string GetHashedString(string data)
 {
 string hash, salt;
 this.GetHashAndSaltString(data, out hash, out salt);
 return hash.Replace(this.delimiter, String.Empty) + this.delimiter + salt.Replace(this.delimiter, string.Empty);
 }

/// <summary>
 /// Verifies the data and hash
 /// </summary>
 /// <param name="data">The data to compare</param>
 /// <param name="hashedData">The hash to compare with</param>
 /// <returns>Returns bool flag</returns>
 public bool VerifyHashString(string data, string hashedData)
 {
 if (String.IsNullOrEmpty(hashedData))
 {
 return false;
 }

string[] split = hashedData.Split(this.delimiter.ToCharArray());

if (split == null || split.Length != 2)
 {
 return false;
 }

return this.VerifyHashString(data, split[0], split[1]);
 }

/// <summary>
 /// The actual hash calculation is shared by both GetHashAndSalt and the VerifyHash functions
 /// </summary>
 /// <param name="data">The data byte array</param>
 /// <param name="salt">The salt byte array</param>
 /// <returns>
 /// A byte array with the calculated hash
 /// </returns>
 private byte[] ComputeHash(byte[] data, byte[] salt)
 {
 // Allocate memory to store both the Data and Salt together
 byte[] dataAndSalt = new byte[data.Length + this.salthLength];

// Copy both the data and salt into the new array
 Array.Copy(data, dataAndSalt, data.Length);
 Array.Copy(salt, 0, dataAndSalt, data.Length, this.salthLength);

// Calculate the hash
 // Compute hash value of our plain text with appended salt.
 return this.hashProvider.ComputeHash(dataAndSalt);
 }

/// <summary>
 /// Given a data block this routine returns both a Hash and a Salt
 /// </summary>
 /// <param name="data">The data byte array</param>
 /// <param name="hash">The hash byte array</param>
 /// <param name="salt">The salt byte array</param>
 private void GetHashAndSalt(byte[] data, out byte[] hash, out byte[] salt)
 {
 // Allocate memory for the salt
 salt = new byte[this.salthLength];

// Strong runtime pseudo-random number generator, on Windows uses CryptAPI
 // on Unix /dev/urandom
 RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();

// Create a random salt
 random.GetNonZeroBytes(salt);

// Compute hash value of our data with the salt.
 hash = this.ComputeHash(data, salt);

random.Dispose();
 }

/// <summary>
 /// The routine provides a wrapper around the GetHashAndSalt function providing conversion
 /// from the required byte arrays to strings. Both the Hash and Salt are returned as Base-64 encoded strings.
 /// </summary>
 /// <param name="data">The data byte array</param>
 /// <param name="hash">The hash byte array</param>
 /// <param name="salt">The salt byte array</param>
 private void GetHashAndSaltString(string data, out string hash, out string salt)
 {
 byte[] hashOut;
 byte[] saltOut;

// Obtain the Hash and Salt for the given string
 this.GetHashAndSalt(Encoding.UTF8.GetBytes(data), out hashOut, out saltOut);

// Transform the byte[] to Base-64 encoded strings
 hash = Convert.ToBase64String(hashOut);
 salt = Convert.ToBase64String(saltOut);
 }

/// <summary>
 /// This routine verifies whether the data generates the same hash as we had stored previously
 /// </summary>
 /// <param name="data">The data byte array</param>
 /// <param name="hash">The hash byte array</param>
 /// <param name="salt">The salt byte array</param>
 /// <returns>
 /// True on a succesful match
 /// </returns>
 private bool VerifyHash(byte[] data, byte[] hash, byte[] salt)
 {
 byte[] newHash = this.ComputeHash(data, salt);

//// Compare hash
 if (newHash.Length != hash.Length)
 {
 return false;
 }

for (int lp = 0; lp < hash.Length; lp++)
 {
 if (!hash[lp].Equals(newHash[lp]))
 {
 return false;
 }
 }

return true;
 }

/// <summary>
 /// This routine provides a wrapper around VerifyHash converting the strings containing the
 /// data, hash and salt into byte arrays before calling VerifyHash.
 /// </summary>
 /// <param name="data">The data byte array</param>
 /// <param name="hash">The hash byte array</param>
 /// <param name="salt">The salt byte array</param>
 /// <returns>
 /// Returns bool flag
 /// </returns>
 private bool VerifyHashString(string data, string hash, string salt)
 {
 byte[] hashToVerify = Convert.FromBase64String(hash);
 byte[] saltToVerify = Convert.FromBase64String(salt);
 byte[] dataToVerify = Encoding.UTF8.GetBytes(data);
 return this.VerifyHash(dataToVerify, hashToVerify, saltToVerify);
 }

#endregion Methods
 }
}

the C# version of the following code

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


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

namespace WindowsFormsApplication5
{
 class Simple3Des
 {
 TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider();

public Simple3Des(string key)
 {
 // Initialize the crypto provider.
 tripleDes.Key = TruncateHash(key, tripleDes.KeySize / 8);
 tripleDes.IV = TruncateHash("", tripleDes.BlockSize / 8);
 }

private byte[] TruncateHash(string key, int length)
 {
 SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
 // Hash the key.
 byte[] keyBytes = System.Text.Encoding.Unicode.GetBytes(key);
 byte[] hash = sha1.ComputeHash(keyBytes);

// Truncate or pad the hash.
 Array.Resize(ref hash, length);
 return hash;
 }

public string EncryptData(string plaintext)
 {

// Convert the plaintext string to a byte array.
 byte[] plaintextBytes = System.Text.Encoding.Unicode.GetBytes(plaintext);

// Create the stream.
 System.IO.MemoryStream ms = new System.IO.MemoryStream();
 // Create the encoder to write to the stream.
 CryptoStream encStream = new CryptoStream(ms, tripleDes.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);

// Use the crypto stream to write the byte array to the stream.
 encStream.Write(plaintextBytes, 0, plaintextBytes.Length);
 encStream.FlushFinalBlock();

// Convert the encrypted stream to a printable string.
 return Convert.ToBase64String(ms.ToArray());
 }

public string DecryptData(string encryptedtext)
 {

// Convert the encrypted text string to a byte array.
 byte[] encryptedBytes = Convert.FromBase64String(encryptedtext);

// Create the stream.
 System.IO.MemoryStream ms = new System.IO.MemoryStream();
 // Create the decoder to write to the stream.
 CryptoStream decStream = new CryptoStream(ms, tripleDes.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Write);

// Use the crypto stream to write the byte array to the stream.
 decStream.Write(encryptedBytes, 0, encryptedBytes.Length);
 decStream.FlushFinalBlock();

// Convert the plaintext stream to a string.
 return System.Text.Encoding.Unicode.GetString(ms.ToArray());
 }

&nbsp;

}
}

Bye.

Improve SSRS reports performance.


Hi,

Found these helpful articles while looking for improving the performance of one of our reports.

Also check this video from Channel 9

http://channel9.msdn.com/Events/TechEd/Europe/2009/DAT306

 

Bye.

Showing related entity information in Header as Hyperlink – CRM 2011


We recently had requirement to show the Case Information in one of its related (related) entity’s header. The information should appear as a hyperlink so that users can open the case directly from that entity’s form.

Case entity was having 1-n relationship with this other entity say Entity A and Entity A was related 1-n with Entity B. In Entity A we had moved the lookup of Case in the header. So from Entity A’s form user could click the lookup in header (as lookup appeared as hyperlink in Header) and open the Case.

Now they wanted the similar kind of functionality in Entity B. However as Entity B was not directly related to Case entity it had no lookup or any other field having Case information in it.

So this is what we did :-

  1. Created a new HTML Web Resource.
  2. Added an anchor tag in it.
  3. Used JavaScript to get the Case Information from the lookup of the Entity A in the form.
  4. Dynamically setting the href and innerHTML of the anchor tag so that it provides case information and link clicking on which should open the case record.
  5. Add the Web Resource in the header of the Entity B form.
  6. As we were using JSON here, added the JSON library in the form load.

    Case Information in the header and the hyperlink:-

Sample Code of the HTML Web Resource:-


<html xmlns="http://www.w3.org/1999/xhtml">
<head>
 <title>Case Information</title>
 <script src="ClientGlobalContext.js.aspx"></script>
 <script type="text/javascript" src="new_json2"></script>
 <style type="text/css">
 .ms-crm-Field-Normal
 {
 font-family: Segoe UI, Tahoma, Arial;
 font-size: 13px;
 position:absolute;
 top:0px;
 text-align: left;
 }


 </style>
 <meta charset="utf-8">
</head>
<body style="background-color: #f7fbff; margin: 10px" onload="GetCaseInformation()"
 contenteditable="true">
 <a id="anchorCase" href="#" target="_blank" class="ms-crm-Field-Normal"></a>
 <script>

var FORM_TYPE_UPDATE = 2;
 var FORM_TYPE_READ_ONLY = 3;
 var FORM_TYPE_DISABLED = 4;


 var ODataPath;
 var serverUrl;
 var entityName = "";
 var id = "";
 var entity;

function GetCaseInformation() {
 init();
 }

function init() {


 serverUrl = document.location.protocol + "//" + document.location.host + "/" + Xrm.Page.context.getOrgUniqueName();
 ODataPath = serverUrl + "/XRMServices/2011/OrganizationData.svc";
 if (parent.Xrm.Page.ui.getFormType() == FORM_TYPE_UPDATE ||
 parent.Xrm.Page.ui.getFormType() == FORM_TYPE_READ_ONLY ||
 parent.Xrm.Page.ui.getFormType() == FORM_TYPE_DISABLED) {

// get the lookup control and its guid and entity type
 var value = parent.Xrm.Page.ui.controls.get('new_casemedicalconditionid').getAttribute().getValue();

if (value != null) {
 id = value[0].id.replace('{', '').replace('}', '');
 entityName = value[0].entityType;
 }
 }
 // get the case information
 retrieveRecord(id);
 }

function retrieveRecord(Id) {
 var retrieveReq = new XMLHttpRequest();
 var url = ODataPath + "/" + entityName + "Set(guid'" + Id + "')";

retrieveReq.open("GET", ODataPath + "/" + entityName + "Set(guid'" + Id + "')", true);
 retrieveReq.setRequestHeader("Accept", "application/json");
 retrieveReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
 retrieveReq.onreadystatechange = function () {
 retrieveReqCallBack(this);
 };
 retrieveReq.send();
 }

function retrieveReqCallBack(retrieveReq) {


 if (retrieveReq.readyState == 4 /* complete */) {
 if (retrieveReq.status == 200) {
 //Success

 entity = JSON.parse(retrieveReq.responseText).d;
 if (entity.new_CaseId != null) {
 var caseGuid = entity.new_CaseId.Id;
 var caseName = entity.new_CaseId.Name;
 var serverUrl = document.location.protocol + "//" + document.location.host + "/" + Xrm.Page.context.getOrgUniqueName();
 if (document.getElementById('anchorCase').innerHTML == "") {
 document.getElementById('anchorCase').innerHTML = caseName;
 document.getElementById('anchorCase').href = serverUrl + "/CS/cases/edit.aspx?id={" + caseGuid + "}";
 }
 }
 }
 }
 }

</script>
</body>
</html>


Bye.

Used Multiple Forms in CRM 2011


As we all know that we have new multiple forms feature in CRM 2011, which allows us to create multiple forms for an entity. Today for the first time I got an opportunity to implement it.

Our scenario was something like this :-

We wanted only specific users to Reactivate Case and they shouldn’t be able to modify any value on the case that they are Reactivating.

We started by first figuring out the minimum rights required to Reactivate the case and they were

  1. Create
  2. Write
  3. Append To

for the Case entity.

Obviously with Write access user will be able to modify the values for the case.

So we did the following

  1. Created a new custom security role having the above mentioned privileges.
  2. Created a new form for the Case Entity.
  3. Removed few of the sections/fields and set the remaining fields as Read Only (through form customization and not JavaScript) for the new form.
  4. Used Assign Security Roles to and selected the newly created security roles as Display only to these selected security roles option


  5. For the main Information form, we selected the same option Display only to these selected security roles and this time checked all other roles and unchecked the new security roles created.

So now when the user having the new security role opens the case form for Reactivating the Case, he only sees the newly created form which has all the fields set as read only.

This solved our purpose.

Hope it helps.

Reactivate Case in CRM 2011


Hi,

Below the minimum rights required to Reactivate a closed or resolved Case in CRM.

Sample code to do it through code


private void Form_Load(object sender, EventArgs e)
 {
 Uri organizationUri = new Uri("http://servername/orgname/XRMServices/2011/Organization.svc");
 Uri homeRealmUri = null;
 ClientCredentials credentials = new ClientCredentials();
 credentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
 OrganizationServiceProxy orgProxy = new OrganizationServiceProxy(organizationUri, homeRealmUri, credentials, null);
 IOrganizationService _service = (IOrganizationService)orgProxy;
 ReactivateState("incident", new Guid("caseGuid"), 0, -1, _service);
 }

public static void ReactivateState(string entityName, Guid entityGuid, int state, int status, IOrganizationService orgService)
 {
 try
 {
 SetStateRequest req = new SetStateRequest();
 req.EntityMoniker = new EntityReference(entityName, entityGuid);
 req.State = new OptionSetValue(state);
 req.Status = new OptionSetValue(status);
 orgService.Execute(req);
 }
 catch (Exception ex)
 {

 }
 }

Bye.

Things to consider while using getServerUrl() in CRM 2011


Hi,

We recently faced an issue after we configured our CRM 2011 site for SSL\HTTPS.

While using context.getServerUrl() method in our web resources we were getting the url value having http instead of https. And the other issue that we regularly faced was the Access Denied one if we access our CRM server either through localhost or through IP address.

These two wonderful posts talk about how to deal with these issues

http://social.microsoft.com/Forums/is/crmdeployment/thread/dc35f48d-f528-44ee-91b5-73b6c42e6217

http://myencounterwithcrm.wordpress.com/2011/05/24/crm-2011-alternative-to-context-getserverurl/

getServerUrl() method returns  the url according to the configured values in the Deployment Manager, not based on the url you have used to navigate to the page

and using

var customServerURL = document.location.protocol + “//” + document.location.host +“/” + Xrm.Page.context.getOrgUniqueName();

Update : It works for on premise scenario only

Check this most helpful post on how to get the server url

http://danielcai.blogspot.com/2012/02/get-right-server-url-in-your-crm-client.html

Hope it helps

Nishant Rana's Weblog

Everything related to Microsoft .NET Technology

Skip to content ↓