Thursday, June 16, 2011

Encrypting & Decrypting XML

I have been given a task to encrypt an xml file before sending it to a different server and use it there after decrypting it just to make the data transfer more secured.

Here is what the code does to encrypt and decrypt an xml file -

This is to be entered in the web.config file -

< system.web>
< machineKey validationKey="1B8B081B3ED61D4663AE0F85406E69A5C8D8D2B8" decryptionKey="77C3813937C1C210054267AC940D0E75A4BD988F095EDE2D"
decryption="3DES"
validation="SHA1"/>

OR

< machineKey
validationKey="AutoGenerate,IsolateApps"
decryptionKey="AutoGenerate,IsolateApps"
validation="SHA1"
decryption="Auto"
/>


Now is the code -

public XmlDocument Config = new XmlDocument();

public string sEnvironment = "";

string sLoc = string.Empty;

protected void Page_Load(object sender, EventArgs e)
{
sLoc = Server.MapPath("XMLFile1.xml");
Config.Load(sLoc);

sEnvironment = "Prod"; // ConfigurationSettings.AppSettings["Environment"].ToString();
if (IsXmlEncrypted(Config))
//Config = DecryptXml(Config);
DecryptXml(sLoc);
else
{
if (sEnvironment != "Local")
{
EncryptXml(sLoc, "root");
}
Config = DecryptXml(Config);
}
}

#region Encrypt and Decrypt Methods

///
/// EncryptXml is a method that will encrypt and entire Xml file, or just a particular node in an Xml. This method accepts 2 parameters: the path where the Xml file is located
/// and the node that must be encrypted. If the entire Xml document needs to be encrypted, the root node of the Xml document must be passed as the node parameter.
/// NOTE: This method SAVES the file! If you do not need to overwrite your Xml file, then DO NOT USE this method. Use the other version in its place.
///

/// The actual path where the Xml file is stored.
/// The node from which encryption starts. If the root node is passed as a parameter, the entire document will be encrypted.
/// If you do not need the entire document encrypted, but instead, just one node, pass the node in in xpath format: "root/parent/child"
///

public void EncryptXml(string file, string node)
{

sLoc = Server.MapPath("web.config");
Config.Load(sLoc);

XmlNode xNode = Config.SelectSingleNode("configuration/system.web/machineKey");

CspParameters cspParams = new CspParameters();

cspParams.KeyContainerName = xNode.Attributes["validationKey"].InnerText;
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;

RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load(file);

XmlElement elementToEncrypt = xmlDoc.GetElementsByTagName(node)[0] as XmlElement;

if (elementToEncrypt != null)
{
RijndaelManaged sessionKey = new RijndaelManaged();
sessionKey.KeySize = 256;

EncryptedXml eXml = new EncryptedXml();

byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, sessionKey, false);
EncryptedData eData = new EncryptedData();
eData.Type = EncryptedXml.XmlEncElementUrl;

eData.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);

EncryptedKey eKey = new EncryptedKey();
byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, rsaKey, false);
eKey.CipherData = new CipherData(encryptedKey);
eKey.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);

eData.KeyInfo = new KeyInfo();

KeyInfoName kin = new KeyInfoName();

kin.Value = xNode.Attributes["decryptionKey"].InnerText;
eKey.KeyInfo.AddClause(kin);

eData.KeyInfo.AddClause(new KeyInfoEncryptedKey(eKey));

eData.CipherData.CipherValue = encryptedElement;
EncryptedXml.ReplaceElement(elementToEncrypt, eData, false);

xmlDoc.Save(file);
}
else
throw new ArgumentNullException("The specified node does not exist in the provided Xml document.");
}

///
/// EncryptXml is a method that will encrypt an Xml file and return an XmlDocument object for use IN MEMORY. If the XmlDocument needs to be saved, then it is up to the calling
/// program to save the encrypted Xml file.
///

/// A previously loaded Xml file that needs to be encrypted.
/// he node from which encryption starts. If the root node is passed as a parameter, the entire document will be encrypted.
/// If you do not need the entire document encrypted, but instead, just one node, pass the node in in xpath format: "root/parent/child"
///
/// An encrypted XmlDocument. How it is used is up to the calling program.

public static XmlDocument EncryptXml(XmlDocument xmlDoc, string node)
{
XmlDocument xmlDocToEncrypt = xmlDoc;
XmlDocument config = DotNetNuke.Common.Utilities.Config.Load();
XmlNode xNode = config.SelectSingleNode("configuration/system.web/machineKey");

CspParameters cspParams = new CspParameters();

cspParams.KeyContainerName = xNode.Attributes["validationKey"].InnerText;
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;

RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

XmlElement elementToEncrypt = xmlDocToEncrypt.GetElementsByTagName(node)[0] as XmlElement;

if (elementToEncrypt != null)
{
RijndaelManaged sessionKey = new RijndaelManaged();
sessionKey.KeySize = 256;

EncryptedXml eXml = new EncryptedXml();

byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, sessionKey, false);
EncryptedData eData = new EncryptedData();
eData.Type = EncryptedXml.XmlEncElementUrl;

eData.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);

EncryptedKey eKey = new EncryptedKey();
byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, rsaKey, false);
eKey.CipherData = new CipherData(encryptedKey);
eKey.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);

eData.KeyInfo = new KeyInfo();

KeyInfoName kin = new KeyInfoName();

kin.Value = xNode.Attributes["decryptionKey"].InnerText;
eKey.KeyInfo.AddClause(kin);

eData.KeyInfo.AddClause(new KeyInfoEncryptedKey(eKey));

eData.CipherData.CipherValue = encryptedElement;
EncryptedXml.ReplaceElement(elementToEncrypt, eData, false);

return xmlDocToEncrypt;
}
else
throw new ArgumentNullException("The specified Xml node does not exist in the provided Xml document.");
}

///
/// This method encrypts a string!
///

/// The string that needs to be encrypted.
/// The encrypted string.

public static string EncryptData(string data)
{
DotNetNuke.Security.PortalSecurity ps = new PortalSecurity();

XmlDocument config = DotNetNuke.Common.Utilities.Config.Load();
XmlNode node = config.SelectSingleNode("configuration/system.web/machineKey");

return ps.Encrypt(node.Attributes["decryptionKey"].InnerText, data);
}

///
/// This method decrypts a previously encrypted string!
///

/// The string that needs to be decrypted.
/// The decrypted string.

public static string DecryptData(string data)
{
DotNetNuke.Security.PortalSecurity ps = new PortalSecurity();

XmlDocument config = DotNetNuke.Common.Utilities.Config.Load();
XmlNode node = config.SelectSingleNode("configuration/system.web/machineKey");

return ps.Decrypt(node.Attributes["decryptionKey"].InnerText, data);
}

///
/// DecryptXml decrypts an Xml file. This method will decrypt the file and then save it to the specified location. If you
/// do not want your original file overwritten, then do not use this method.
///

/// The path of the encrypted Xml file.

public void DecryptXml(string file)
{
sLoc = Server.MapPath("web.config");
Config.Load(sLoc);

XmlNode xNode = Config.SelectSingleNode("configuration/system.web/machineKey");

CspParameters cspParams = new CspParameters();

cspParams.KeyContainerName = xNode.Attributes["validationKey"].InnerText;
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;

RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load(file);

EncryptedXml eXml = new EncryptedXml(xmlDoc);
eXml.AddKeyNameMapping(xNode.Attributes["decryptionKey"].InnerText, rsaKey);

eXml.DecryptDocument();

try
{
xmlDoc.Save(file);
}
catch (XmlException ex)
{
DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
}
}

///
/// This version of DecryptXml will decrypt a given Xml file for use in memory. If the file needs to be saved, it is up to the calling program to handle that.
///

/// The encrypted Xml document that must be decrypted
/// The node within the document that is to be decrypted

public XmlDocument DecryptXml(XmlDocument xDoc)
{
sLoc = Server.MapPath("web.config");
Config.Load(sLoc);

XmlNode xNode = Config.SelectSingleNode("configuration/system.web/machineKey");

XmlDocument xmlDoc = xDoc;

CspParameters cspParams = new CspParameters();

cspParams.KeyContainerName = xNode.Attributes["validationKey"].InnerText;
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;

RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

EncryptedXml eXml = new EncryptedXml(xmlDoc);
eXml.AddKeyNameMapping(xNode.Attributes["decryptionKey"].InnerText, rsaKey);

eXml.DecryptDocument();

return xmlDoc;
}

///
/// This method will determine if the "EncryptedData" node exists. If so, then this file has been encrypted.
///

/// The xml file to test for encryption.
/// TRUE OR FALSE

public static bool IsXmlEncrypted(XmlDocument xDoc)
{
XmlElement eData = xDoc.GetElementsByTagName("EncryptedData")[0] as XmlElement;

if (eData != null)
return true;
else
return false;
}

Tuesday, June 14, 2011

Reseed the Auto increment field

You can reseed the Auto increment field to the desired number by using the following SQL statement -
[I think it is specific for SQL Server only] other Database have their own methods.

Syntax :-

DBCC CHECKIDENT ("TableName", RESEED, 0)