AES encryption in JavaScript and decryption in C#

We need to include aes.js and pbkdf2.js javascript files to use this code. These files can be downloaded from code.google.com/p/crypto-js

function EncryptData()
        {
            var PlainText = document.getElementById('TextOriginal').value;
            var encryptData = document.getElementById('TextEncryptedJS');

            try {
                //Creating the Vector Key
                var iv = CryptoJS.enc.Hex.parse('a5s8d2e9c1721ae0e84ad660c472y1f3');
                //Encoding the Password in from UTF8 to byte array
                var Pass = CryptoJS.enc.Utf8.parse('Crypto');
                //Encoding the Salt in from UTF8 to byte array
                var Salt = CryptoJS.enc.Utf8.parse("cryptography123example");
                //Creating the key in PBKDF2 format to be used during the encryption
                var key128Bits1000Iterations = CryptoJS.PBKDF2(Pass.toString(CryptoJS.enc.Utf8), Salt, { keySize: 128 / 32, iterations: 1000 });

                //Encrypting the string contained in cipherParams using the PBKDF2 key
                var encrypted = CryptoJS.AES.encrypt(PlainText, key128Bits1000Iterations, { mode: CryptoJS.mode.CBC, iv: iv, padding: CryptoJS.pad.Pkcs7 });
                encryptData.value = encrypted.ciphertext.toString(CryptoJS.enc.Base64);
            }
            //Malformed UTF Data due to incorrect password
            catch (err) {
                return "";
            }
        }

To Decrypt this string in C# we need to add a class file named “ClsCrypto.cs”. Here is the code for ClsCrypto class :

public class ClsCrypto
    {
        private RijndaelManaged myRijndael = new RijndaelManaged();
        private int iterations;
        private byte [] salt;

        public ClsCrypto(string strPassword)
        {
            myRijndael.BlockSize = 128;
            myRijndael.KeySize = 128;
            myRijndael.IV = HexStringToByteArray("a5s8d2e9c1721ae0e84ad660c472y1f3");

            myRijndael.Padding = PaddingMode.PKCS7;
            myRijndael.Mode = CipherMode.CBC;
            iterations = 1000;
            salt = System.Text.Encoding.UTF8.GetBytes("cryptography123example");
            myRijndael.Key = GenerateKey(strPassword);
        }

        public string Encrypt(string strPlainText)
        {
            byte [] strText = new System.Text.UTF8Encoding().GetBytes(strPlainText);
            ICryptoTransform transform = myRijndael.CreateEncryptor();
            byte [] cipherText = transform.TransformFinalBlock(strText, 0, strText.Length);
            return Convert.ToBase64String(cipherText);
        }

        public string Decrypt(string encryptedText)
        {
            var encryptedBytes = Convert.FromBase64String(encryptedText);
            ICryptoTransform transform = myRijndael.CreateDecryptor();
            byte[] cipherText = transform.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
            return System.Text.Encoding.UTF8.GetString(cipherText);
        }

        public static byte [] HexStringToByteArray(string strHex)
        {
            dynamic r = new byte[strHex.Length / 2];
            for (int i = 0; i <= strHex.Length - 1; i += 2)
            {
                r[i/2] = Convert.ToByte(Convert.ToInt32(strHex.Substring(i, 2), 16));
            }
            return r;
        }

        private byte[] GenerateKey(string strPassword)
        {
            Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(System.Text.Encoding.UTF8.GetBytes(strPassword), salt, iterations);
            return rfc2898.GetBytes(128 / 8);
        }
    }

In ClsCrypto method we have a parameter for “strPassword”, it must be the same as we have in javascript code.

 ClsCrypto crypto = new ClsCrypto("Crypto");
 string DecrypedString = crypto.Decrypt("Encrypted Text");

Set State or Status of a record using JavaScript in MS Dynamics CRM

This example will show you, how to change the state or status of an entity record in  Microsoft Dynamics CRM 2011 & 2013 with “SetStateRequest”  using JavaScript.

var setStateRequest = function(_entityname, entityid, _state, _status, successCallback, errorCallback) {
var requestMain = ""
requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
requestMain += "  <s:Body>";
requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
requestMain += "      <request i:type=\"b:SetStateRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">";
requestMain += "        <a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
requestMain += "          <a:KeyValuePairOfstringanyType>";
requestMain += "            <c:key>EntityMoniker</c:key>";
requestMain += "            <c:value i:type=\"a:EntityReference\">";
requestMain += "              <a:Id>" + entityid + "</a:Id>";
requestMain += "              <a:LogicalName>" + _entityname + "</a:LogicalName>";
requestMain += "              <a:Name i:nil=\"true\" />";
requestMain += "            </c:value>";
requestMain += "          </a:KeyValuePairOfstringanyType>";
requestMain += "          <a:KeyValuePairOfstringanyType>";
requestMain += "            <c:key>State</c:key>";
requestMain += "            <c:value i:type=\"a:OptionSetValue\">";
requestMain += "              <a:Value>" + _state + "</a:Value>";
requestMain += "            </c:value>";
requestMain += "          </a:KeyValuePairOfstringanyType>";
requestMain += "          <a:KeyValuePairOfstringanyType>";
requestMain += "            <c:key>Status</c:key>";
requestMain += "            <c:value i:type=\"a:OptionSetValue\">";
requestMain += "              <a:Value>" + _status + "</a:Value>";
requestMain += "            </c:value>";
requestMain += "          </a:KeyValuePairOfstringanyType>";
requestMain += "        </a:Parameters>";
requestMain += "        <a:RequestId i:nil=\"true\" />";
requestMain += "        <a:RequestName>SetState</a:RequestName>";
requestMain += "      </request>";
requestMain += "    </Execute>";
requestMain += "  </s:Body>";
requestMain += "</s:Envelope>";
var req = new XMLHttpRequest();
req.open("POST", getServerUrl(), false)
// Responses will return XML. It isn't possible to return JSON.
req.setRequestHeader("Accept", "application/xml, text/xml, */*");
req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
req.onreadystatechange = function() { setStateResponse(req, successCallback, errorCallback); };
req.send(requestMain);
};

var setStateResponse = function(req, successCallback, errorCallback) {
if (req.readyState == 4) {
if (req.status == 200) {
if (successCallback != null) {
successCallback();
}
} else {
errorCallback(getError(req.responseXML));
}
}
};

Hope this helps !

AES encryption in C# and decryption in JavaScript

To use AES encryption in C# we need to add a class file named “ClsCrypto.cs”. Here is the code for ClsCrypto class :

public class ClsCrypto
    {
        private RijndaelManaged myRijndael = new RijndaelManaged();
        private int iterations;
        private byte [] salt;

        public ClsCrypto(string strPassword)
        {
            myRijndael.BlockSize = 128;
            myRijndael.KeySize = 128;
            myRijndael.IV = HexStringToByteArray("a5s8d2e9c1721ae0e84ad660c472y1f3");

            myRijndael.Padding = PaddingMode.PKCS7;
            myRijndael.Mode = CipherMode.CBC;
            iterations = 1000;
            salt = System.Text.Encoding.UTF8.GetBytes("cryptography123example");
            myRijndael.Key = GenerateKey(strPassword);
        }

        public string Encrypt(string strPlainText)
        {
            byte [] strText = new System.Text.UTF8Encoding().GetBytes(strPlainText);
            ICryptoTransform transform = myRijndael.CreateEncryptor();
            byte [] cipherText = transform.TransformFinalBlock(strText, 0, strText.Length);
            return Convert.ToBase64String(cipherText);
        }

        public string Decrypt(string encryptedText)
        {
            var encryptedBytes = Convert.FromBase64String(encryptedText);
            ICryptoTransform transform = myRijndael.CreateDecryptor();
            byte[] cipherText = transform.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
            return System.Text.Encoding.UTF8.GetString(cipherText);
        }

        public static byte [] HexStringToByteArray(string strHex)
        {
            dynamic r = new byte[strHex.Length / 2];
            for (int i = 0; i <= strHex.Length - 1; i += 2)
            {
                r[i/2] = Convert.ToByte(Convert.ToInt32(strHex.Substring(i, 2), 16));
            }
            return r;
        }

        private byte[] GenerateKey(string strPassword)
        {
            Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(System.Text.Encoding.UTF8.GetBytes(strPassword), salt, iterations);
            return rfc2898.GetBytes(128 / 8);
        }
    }

In ClsCrypto method we have a parameter for “strPassword”, it will be same when we decrypt using javascript code.

 ClsCrypto crypto = new ClsCrypto("Crypto");
 string EncryptedString = crypto.Encrypt("Text to encrypt");

We need to include aes.js and pbkdf2.js javascript files to use this code. These files can be downloaded from code.google.com/p/crypto-js

function DecryptData(encryptedData)
        {            
            var decryptedText = null;
            try
            {
                //Creating the Vector Key
                var iv = CryptoJS.enc.Hex.parse('a5s8d2e9c1721ae0e84ad660c472y1f3');
                //Encoding the Password in from UTF8 to byte array
                var Pass = CryptoJS.enc.Utf8.parse('Crypto');
                //Encoding the Salt in from UTF8 to byte array
                var Salt = CryptoJS.enc.Utf8.parse("cryptography123example");
                //Creating the key in PBKDF2 format to be used during the decryption
                var key128Bits1000Iterations = CryptoJS.PBKDF2(Pass.toString(CryptoJS.enc.Utf8), Salt, { keySize: 128 / 32, iterations: 1000 });
                //Enclosing the test to be decrypted in a CipherParams object as supported by the CryptoJS libarary
                var cipherParams = CryptoJS.lib.CipherParams.create({
                    ciphertext: CryptoJS.enc.Base64.parse(encryptedData)
                });

                //Decrypting the string contained in cipherParams using the PBKDF2 key
                var decrypted = CryptoJS.AES.decrypt(cipherParams, key128Bits1000Iterations, { mode: CryptoJS.mode.CBC, iv: iv, padding: CryptoJS.pad.Pkcs7 });
                decryptedText = decrypted.toString(CryptoJS.enc.Utf8);
                return decryptedText;
            }
            //Malformed UTF Data due to incorrect password
            catch (err) {
                return "";
            }
        }

Retrieve CRM 2013 State and Status Code using JavaScript.

With the help of  oData we can get the value of the statuscode field but not for the statecode field. While looking for the best possible way to get the statecode alongwith the statuscode in javascript came to know about the sdk.metadata.js sample code in SDK (sdk\samplecode\js\soapforjscript\soapforjscript\scripts)

There is a RetrieveAttribute method which can be used to get the attribute metadata.This is how we fetched all the label and value for the state and status in CRM.

function GetEntityStateAndStatus(EntityName) {
    var AttributeLogicalName = "statuscode";
    var MetadataId = "00000000-0000-0000-0000-000000000000";
    SDK.Metadata.RetrieveAttribute(EntityName, AttributeLogicalName, MetadataId, true,
    function (result) {
        SDK.SAMPLES.success(result);
    },
    function (error) { }
    );
}
function successCallBack(result) {
    for (var i = 0; i < result.OptionSet.Options.length; i++) {
        var stateValue = result.OptionSet.Options[i].State;
        var statusValue = result.OptionSet.Options[i].Value;
        var statusText = result.OptionSet.Options[i].Label.LocalizedLabels[0].Label;
    }
}

Get OptionSet Text by Value in MS CRM

To get the optionSet, please refer “https://codingclub.wordpress.com/2014/06/24/get-optionset-in-ms-crm&#8221;

getTextByValue: function (optionSet, attributeValue) {
        if (Mscrm.Utilities.isChrome()) {
            var options = optionSet.getElementsByTagName("Options")[0];
            for (var i = 0; i < options.childNodes.length; i++) {
                var value = options.childNodes[i].getElementsByTagName("Value")[0].textContent;
                if (value == attributeValue) {
                    var text = options.childNodes[i].getElementsByTagName("Label")[0].getElementsByTagName("UserLocalizedLabel")[0].getElementsByTagName("Label")[0].textContent;
                    return text;
                }
            }
        }
        else if (Mscrm.Utilities.isIE8() || Mscrm.Utilities.isIE9()) {
            var options = optionSet.selectSingleNode("c:OptionSet//c:Options");
            for (var i = 0; i < options.childNodes.length; i++) {
                var value = options.childNodes[i].selectSingleNode("c:Value").text;
                if (value == attributeValue) {
                    var text = options.childNodes[i].selectSingleNode("c:Label").selectSingleNode("a:UserLocalizedLabel").selectSingleNode("a:Label").text;
                    return text;
                }
            }
        }
        else {
            var options = optionSet.getElementsByTagName("c:Options")[0];
            for (var i = 0; i < options.childNodes.length; i++) {
                var value = options.childNodes[i].getElementsByTagName("c:Value")[0].textContent;
                if (value == attributeValue) {
                    var text = options.childNodes[i].getElementsByTagName("c:Label")[0].getElementsByTagName("a:UserLocalizedLabel")[0].getElementsByTagName("a:Label")[0].textContent;
                    return text;
                }
            }
        }
    },

Get Optionset in MS CRM

getOptionSet: function (entityLogicalName, attributeLogicalName, retrieveAsIfPublished) {
 var url = Xrm.Page.context.getServerUrl() + "/XRMServices/2011/Organization.svc/web";
 var MetadataId = "00000000-0000-0000-0000-000000000000";
 var request = "<Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
 request += "<request i:type=\"a:RetrieveAttributeRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
 request += "<a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
 request += "<a:KeyValuePairOfstringanyType>";
 request += "<b:key>EntityLogicalName</b:key>";
 request += "<b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + entityLogicalName + "</b:value>";
 request += "</a:KeyValuePairOfstringanyType>";
 request += "<a:KeyValuePairOfstringanyType>";
 request += "<b:key>MetadataId</b:key>";
 request += "<b:value i:type=\"ser:guid\" xmlns:ser=\"http://schemas.microsoft.com/2003/10/Serialization/\">" + MetadataId + "</b:value>";
 request += "</a:KeyValuePairOfstringanyType>";
 request += "<a:KeyValuePairOfstringanyType>";
 request += "<b:key>RetrieveAsIfPublished</b:key>";
 request += "<b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + retrieveAsIfPublished + "</b:value>";
 request += "</a:KeyValuePairOfstringanyType>";
 request += "<a:KeyValuePairOfstringanyType>";
 request += "<b:key>LogicalName</b:key>";
 request += "<b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + attributeLogicalName + "</b:value>";
 request += "</a:KeyValuePairOfstringanyType>";
 request += "</a:Parameters>";
 request += "<a:RequestId i:nil=\"true\" /><a:RequestName>RetrieveAttribute</a:RequestName></request>";
 request += "</Execute>";
 request = this._getSOAPWrapper(request);
 var req = new XMLHttpRequest();
 req.open("POST", url, false);
 req.setRequestHeader("Accept", "application/xml, text/xml, */*");
 req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
 req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
 req.send(request);

 if (req.responseXML != null) {
 if (Mscrm.Utilities.isChrome()) {
 if (window.DOMParser) {
 var parser, resultDoc;
 parser = new DOMParser();
 resultDoc = parser.parseFromString(req.responseText, "text/xml");
 // Webkit
 resultDoc = resultDoc.getElementsByTagName("value")[0];
 var attributeData = resultDoc;
 if (attributeData != null) {
 var attributeType = attributeData.getElementsByTagName("AttributeType")[0].textContent;
 switch (attributeType) {
 case "Picklist":
 return attributeData;
 break;
 default:
 break;
 }
 }
 }
 }
 else if (Mscrm.Utilities.isIE8() || Mscrm.Utilities.isIE9()) {
 var attributeData = req.responseXML.selectSingleNode("//b:value");
 if (attributeData != null) {
 var attributeType = attributeData.selectSingleNode("c:AttributeType").text;
 switch (attributeType) {
 case "Picklist":
 return attributeData;
 break;
 default:
 break;
 }
 }
 }
 else { 
 var attributeData = req.responseXML.getElementsByTagName("b:value")[0];
 if (attributeData != null) {
 var attributeType = attributeData.getElementsByTagName("c:AttributeType")[0].textContent;
 switch (attributeType) {
 case "Picklist":
 return attributeData;
 break;
 default:
 break;
 }
 }
 }
 }

 },

 _getSOAPWrapper: function (request) {
 var SOAP = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Body>";
 SOAP += request;
 SOAP += "</soapenv:Body></soapenv:Envelope>";
 return SOAP;
 },