首页 文章

利用ASP.NET machineKey加密我自己的数据

提问于
浏览
45

我想在ASP.NET MVC应用程序中加密一些数据,以防止用户篡改它 . 我可以使用Cryptography类来进行实际的加密/解密,没问题 . 主要问题是找出存储加密密钥的位置并管理对其的更改 .

由于ASP.NET已经为各种事物维护了一个machineKey(ViewData加密等),我想知道是否有任何ASP.NET函数允许我使用machineKey加密/解密我自己的数据?这样我就不必设计自己的密钥管理系统 .

5 回答

  • 0

    您可以重用MembershipProvider.EncryptPassword方法,后者又使用MachineKeySection类的一些(不幸的是内部)加密方法 .

  • 3

    使用.NET Framwork 4.5,您应该使用新的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;
        }
    
    }
    

    理想情况下,“目的”应该是已知的一次有效值以防止伪造 .

  • 40

    ASP.NET 4.0中的新MachineKey类完全符合您的要求 .

    例如:

    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 :如上所述here,请注意如何使用它,或者您可以允许某人伪造表单身份验证令牌 .

  • 48

    我想不是直接的 . 我不记得我从哪里得到这个,可能是Reflector和一些博客的组合 .

    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;
        }
    }
    

    买者自负!

  • 9

    如果您使用的是3.5或更早版本,则可以避免大量代码并执行此操作:

    public static string Encrypt(string cookieValue)
    {
        return FormsAuthentication.Encrypt(new FormsAuthenticationTicket(1,
                                                                         string.Empty,
                                                                         DateTime.Now,
                                                                         DateTime.Now.AddMinutes(20160),
                                                                         true,
                                                                         cookieValue));
    }
    
    public static string Decrypt(string encryptedTicket)
    {
        return FormsAuthentication.Decrypt(encryptedTicket).UserData;
    }
    

    我的一位同事和我进行了交谈,我认为对于自定义cookie这样做是相当合理的,如果不是因为一般的加密需求 .

相关问题