using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Security.Cryptography; using System.Security.Cryptography.Xml; using System.Xml; namespace EduNetworkBuilder { /// /// Copied from https://msdn.microsoft.com/en-us/library/system.security.cryptography.xml.encryptedxml(v=vs.110).aspx /// class TrippleDESDocumentEncryption { protected XmlDocument docValue; protected TripleDES algValue; /// /// The characters we use for passwords and salts. /// protected const string PWChars = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ234567890_.!#$^*"; public TrippleDESDocumentEncryption(XmlDocument Doc, TripleDES Key) { if (Doc != null) { docValue = Doc; } else { throw new ArgumentNullException("Doc"); } if (Key != null) { algValue = Key; } else { throw new ArgumentNullException("Key"); } } public XmlDocument Doc { set { docValue = value; } get { return docValue; } } public TripleDES Alg { set { algValue = value; } get { return algValue; } } public void Clear() { if (algValue != null) { algValue.Clear(); } else { throw new Exception("No TripleDES key was found to clear."); } } public void Encrypt(string Element) { // Find the element by name and create a new // XmlElement object. XmlElement inputElement = docValue.GetElementsByTagName(Element)[0] as XmlElement; // If the element was not found, throw an exception. if (inputElement == null) { throw new Exception("The element was not found."); } // Create a new EncryptedXml object. EncryptedXml exml = new EncryptedXml(docValue); // Encrypt the element using the symmetric key. byte[] rgbOutput = exml.EncryptData(inputElement, algValue, false); // Create an EncryptedData object and populate it. EncryptedData ed = new EncryptedData(); // Specify the namespace URI for XML encryption elements. ed.Type = Element + " " + EncryptedXml.XmlEncElementUrl; // Specify the namespace URI for the TrippleDES algorithm. ed.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncTripleDESUrl); // Create a CipherData element. ed.CipherData = new CipherData(); // Set the CipherData element to the value of the encrypted XML element. ed.CipherData.CipherValue = rgbOutput; // Replace the plaintext XML elemnt with an EncryptedData element. EncryptedXml.ReplaceElement(inputElement, ed, false); } XmlElement ChooseBestElement(string preferType) { XmlNodeList xnl = docValue.GetElementsByTagName("EncryptedData"); foreach (XmlElement one in xnl.OfType()) { string TypeAttr = one.GetAttribute("Type"); if (TypeAttr != null && TypeAttr.StartsWith(preferType)) return one; } return xnl[0] as XmlElement; } public void Decrypt(string preferType) { // XmlElement object. XmlElement encryptedElement = ChooseBestElement(preferType); // If the EncryptedData element was not found, throw an exception. if (encryptedElement == null) { throw new Exception("The EncryptedData element was not found."); } // Create an EncryptedData object and populate it. EncryptedData ed = new EncryptedData(); ed.LoadXml(encryptedElement); // Create a new EncryptedXml object. EncryptedXml exml = new EncryptedXml(); // Decrypt the element using the symmetric key. try { //Do the decryption byte[] rgbOutput = exml.DecryptData(ed, algValue); // Replace the encryptedData element with the plaintext XML elemnt. exml.ReplaceData(encryptedElement, rgbOutput); } catch { //The decryption failed. throw new LoginException("Key/Salt unable to decrypt."); } } protected static string GenCharString(Random RanGen, int length) { int next; string result = ""; for(int i=0; i< length; i++) { next = RanGen.Next(PWChars.Length); result += PWChars[next]; } return result; } public static string GenSalt(Random RanGen) { return GenSalt(RanGen, NB.DefaultSaltLen); } public static string GenSalt(Random RanGen, int length) { return GenCharString(RanGen, length); } public static string GenUserPW(Random RanGen) { return GenUserPW(RanGen, NB.DefaultPasswordLen); } public static string GenMachinePW(Random RanGen) { return GenUserPW(RanGen, NB.DefaultMachinePasswordLen); } public static string GenUserPW(Random RanGen, int length) { return GenCharString(RanGen, length); } public static TripleDES GenKey(string password, string salt) { TripleDESCryptoServiceProvider tDESkey = new TripleDESCryptoServiceProvider(); byte[] saltBytes = Encoding.UTF8.GetBytes(salt); var p = new Rfc2898DeriveBytes(password, saltBytes); tDESkey.IV = p.GetBytes(tDESkey.BlockSize / 8); tDESkey.Key = p.GetBytes(tDESkey.KeySize / 8); return tDESkey; } public void SetKey(string password, string salt) { algValue = GenKey(password, salt); } } /// /// Create a simple login exception that we can throw when we try to decrypt and it fails /// public class LoginException : System.Exception { public LoginException() : base() { } public LoginException(String message) : base(message) { } public LoginException(String message, Exception innerException) : base(message, innerException) { } } }