using System; using System.Security.Cryptography; namespace Sleis.Utility { public class EncryptionUtility { private readonly System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding(); private readonly string _passphrase; private readonly int _tokenValidForHours; public EncryptionUtility(string passphrase, int tokenValidForHours) { ArgumentValidationUtility.ThrowOnEmpty(passphrase, "passphrase required"); if (tokenValidForHours < 1){ throw new ArgumentOutOfRangeException("Must be greater than one hour"); } _passphrase = passphrase; _tokenValidForHours = tokenValidForHours; } public string EncryptTokenForUrl(int id) { string val = String.Format("{0}|{1}", id, DateTime.Now); return EncryptStringForUrl(val); } public int DecryptTokenFromUrl(string content) { string val = content.Replace("--B--", "+") .Replace("--F--", "/") .Replace("--0--", " ") .Replace("--Q--", "?") .Replace("--A--", "&"); val = DecryptStringFromUrl(val); string[] tokenParts = val.Split('|'); if (tokenParts.Length != 2) { throw new ArgumentOutOfRangeException("Invalid number of token parts"); } DateTime tokenCreatedOn = Convert.ToDateTime(tokenParts[1]); TimeSpan tokenSpan = DateTime.Now - tokenCreatedOn; if (tokenSpan.TotalHours > _tokenValidForHours) { throw new ArgumentOutOfRangeException("Token expired"); } int id = Convert.ToInt32(tokenParts[0]); return id; } public string EncryptStringForUrl(string content) { string val = TripleDESEncrypt(content); val = val.Replace("+", "--B--") .Replace("/", "--F--") .Replace(" ", "--0--") .Replace("?", "--Q--") .Replace("&", "--A--"); return val; } public string DecryptStringFromUrl(string content) { string val = content.Replace("***B***", "+") .Replace("***F***", "/") .Replace("***0***", " ") .Replace("***Q***", "?") .Replace("***A***", "&"); val = TripleDESDecrypt(val); return val; } /// /// Performs a one-way hash /// /// /// SHA512 hash, base 64 encoded (88 char output). With no salt specified, the output will be 100 characters long public string OneWayHash(string content) { ArgumentValidationUtility.ThrowOnEmpty(content, "content required"); var contentBytes = new System.Text.UnicodeEncoding().GetBytes(_passphrase + content); var hashBytes = new SHA512Managed().ComputeHash(contentBytes); return System.Convert.ToBase64String(hashBytes); } /// /// Encrypt in a way that we can decrypt it later /// /// String to encrypt /// Base 64 encoded string public string TripleDESEncrypt(string content) { ArgumentValidationUtility.ThrowOnEmpty(content, "content required"); byte[] results = null; MD5CryptoServiceProvider hashProvider = new MD5CryptoServiceProvider(); byte[] tdesKey = hashProvider.ComputeHash(UTF8.GetBytes(_passphrase)); TripleDESCryptoServiceProvider tdesAlgorithm = new TripleDESCryptoServiceProvider(); tdesAlgorithm.Key = tdesKey; tdesAlgorithm.Mode = CipherMode.ECB; tdesAlgorithm.Padding = PaddingMode.PKCS7; byte[] dataToEncrypt = UTF8.GetBytes(content); try { ICryptoTransform encryptor = tdesAlgorithm.CreateEncryptor(); results = encryptor.TransformFinalBlock(dataToEncrypt, 0, dataToEncrypt.Length); } finally { tdesAlgorithm.Clear(); hashProvider.Clear(); } return Convert.ToBase64String(results); } /// /// Decrypt previously encrypted string /// /// Base 64 encoded string /// Decrypted string public string TripleDESDecrypt(string content) { ArgumentValidationUtility.ThrowOnEmpty(content, "content required"); byte[] results = null; MD5CryptoServiceProvider hashProvider = new MD5CryptoServiceProvider(); byte[] tdesKey = hashProvider.ComputeHash(UTF8.GetBytes(_passphrase)); TripleDESCryptoServiceProvider tdesAlgorithm = new TripleDESCryptoServiceProvider(); tdesAlgorithm.Key = tdesKey; tdesAlgorithm.Mode = CipherMode.ECB; tdesAlgorithm.Padding = PaddingMode.PKCS7; byte[] dataToDecrypt = Convert.FromBase64String(content); try { ICryptoTransform decryptor = tdesAlgorithm.CreateDecryptor(); results = decryptor.TransformFinalBlock(dataToDecrypt, 0, dataToDecrypt.Length); } finally { tdesAlgorithm.Clear(); hashProvider.Clear(); } return UTF8.GetString(results); } } }