Leveraging ASP.NET machineKey For Encrypting My Own Data Leveraging ASP.NET machineKey For Encrypting My Own Data asp.net asp.net

Leveraging ASP.NET machineKey For Encrypting My Own Data


With .NET Framwork 4.5 you should use the new API:

public class StringProtector{    private const string Purpose = "Authentication Token";    public string Protect(string unprotectedText)    {        var unprotectedBytes = Encoding.UTF8.GetBytes(unprotectedText);        var protectedBytes = MachineKey.Protect(unprotectedBytes, Purpose);        var protectedText = Convert.ToBase64String(protectedBytes);        return protectedText;    }    public string Unprotect(string protectedText)    {        var protectedBytes = Convert.FromBase64String(protectedText);        var unprotectedBytes = MachineKey.Unprotect(protectedBytes, Purpose);        var unprotectedText = Encoding.UTF8.GetString(unprotectedBytes);        return unprotectedText;    }}

Ideally the "Purpose" should be a known one time valid value to prevent forging.


The new MachineKey class in ASP.NET 4.0 does exactly what you want.

For example:

public static class StringEncryptor {    public static string Encrypt(string plaintextValue) {        var plaintextBytes = Encoding.UTF8.GetBytes(plaintextValue);        return MachineKey.Encode(plaintextBytes, MachineKeyProtection.All);    }    public static string Decrypt(string encryptedValue) {        try {            var decryptedBytes = MachineKey.Decode(encryptedValue, MachineKeyProtection.All);            return Encoding.UTF8.GetString(decryptedBytes);        }        catch {            return null;        }    }}

UPDATE: As mentioned here, be careful how you use this or you could allow someone to forge a forms authentication token.


I guess not directly. I can't remember where I got this from, probably a combination of Reflector and some blogs.

public abstract class MyAwesomeClass{    private static byte[] cryptKey;    private static MachineKeySection machineKeyConfig =        (MachineKeySection)ConfigurationManager            .GetSection("system.web/machineKey");    // ... snip ...    static MyAwesomeClass()    {        string configKey;        byte[] key;        configKey = machineKeyConfig.DecryptionKey;        if (configKey.Contains("AutoGenerate"))        {            throw new ConfigurationErrorsException(                Resources.MyAwesomeClass_ExplicitAlgorithmRequired);        }        key = HexStringToByteArray(configKey);        cryptKey = key;    }    // ... snip ...    protected static byte[] Encrypt(byte[] inputBuffer)    {        SymmetricAlgorithm algorithm;        byte[] outputBuffer;        if (inputBuffer == null)        {            throw new ArgumentNullException("inputBuffer");        }        algorithm = GetCryptAlgorithm();        using (var ms = new MemoryStream())        {            algorithm.GenerateIV();            ms.Write(algorithm.IV, 0, algorithm.IV.Length);            using (var cs = new CryptoStream(                 ms,                  algorithm.CreateEncryptor(),                  CryptoStreamMode.Write))            {                cs.Write(inputBuffer, 0, inputBuffer.Length);                cs.FlushFinalBlock();            }            outputBuffer = ms.ToArray();        }        return outputBuffer;    }    protected static byte[] Decrypt(string input)    {        SymmetricAlgorithm algorithm;        byte[] inputBuffer, inputVectorBuffer, outputBuffer;        if (input == null)        {            throw new ArgumentNullException("input");        }        algorithm = GetCryptAlgorithm();        outputBuffer = null;        try        {            inputBuffer = Convert.FromBase64String(input);            inputVectorBuffer = new byte[algorithm.IV.Length];            Array.Copy(                 inputBuffer,                  inputVectorBuffer,                 inputVectorBuffer.Length);            algorithm.IV = inputVectorBuffer;            using (var ms = new MemoryStream())            {                using (var cs = new CryptoStream(                    ms,                     algorithm.CreateDecryptor(),                     CryptoStreamMode.Write))                {                    cs.Write(                        inputBuffer,                        inputVectorBuffer.Length,                         inputBuffer.Length - inputVectorBuffer.Length);                    cs.FlushFinalBlock();                }                outputBuffer = ms.ToArray();            }        }        catch (FormatException e)        {            throw new CryptographicException(                "The string could not be decoded.", e);        }        return outputBuffer;    }    // ... snip ...    private static SymmetricAlgorithm GetCryptAlgorithm()    {        SymmetricAlgorithm algorithm;        string algorithmName;        algorithmName = machineKeyConfig.Decryption;        if (algorithmName == "Auto")        {            throw new ConfigurationErrorsException(                Resources.MyAwesomeClass_ExplicitAlgorithmRequired);        }        switch (algorithmName)        {            case "AES":                algorithm = new RijndaelManaged();                break;            case "3DES":                algorithm = new TripleDESCryptoServiceProvider();                break;            case "DES":                algorithm = new DESCryptoServiceProvider();                break;            default:                throw new ConfigurationErrorsException(                    string.Format(                        CultureInfo.InvariantCulture,                        Resources.MyAwesomeClass_UnrecognizedAlgorithmName,                        algorithmName));        }        algorithm.Key = cryptKey;        return algorithm;    }    private static byte[] HexStringToByteArray(string str)    {        byte[] buffer;        if (str == null)        {            throw new ArgumentNullException("str");        }        if (str.Length % 2 == 1)        {            str = '0' + str;        }        buffer = new byte[str.Length / 2];        for (int i = 0; i < buffer.Length; ++i)        {            buffer[i] = byte.Parse(                str.Substring(i * 2, 2),                NumberStyles.HexNumber,                CultureInfo.InvariantCulture);        }        return buffer;    }}

Caveat emptor!