代码之家  ›  专栏  ›  技术社区  ›  dso

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

  •  45
  • dso  · 技术社区  · 14 年前

    我有一些数据,我想加密在一个asp.net mvc应用程序,以防止用户篡改它。我可以使用密码学类进行实际的加密/解密,没有问题。主要问题是找出加密密钥的存储位置并管理对其的更改。

    由于asp.net已经为各种事情(viewdata encryption,等等)维护了machinekey,我想知道是否有任何asp.net函数允许我使用machinekey加密/解密自己的数据?这样我就不用设计自己的密钥管理系统了。

    5 回复  |  直到 14 年前
        1
  •  48
  •   Marco Bettiolo    12 年前

    对于.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;
        }
    
    }
    

    理想情况下,“目的”应为已知的一次性有效值,以防止锻造。

        2
  •  40
  •   Jeff Moser    12 年前

    新的 MachineKey ASP.NET4.0中的类正是您所希望的。

    例如:

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

    更新 :如上所述 here ,请注意如何使用它,或者允许某人伪造表单身份验证令牌。

        3
  •  9
  •   Nicholas Piasecki    14 年前

    我想不是直接的。我不记得这是从哪里来的,可能是反射器和一些博客的结合。

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

    当心清空!

        4
  •  3
  •   Nariman    12 年前

    如果使用的是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这样做是相当合理的。

        5
  •  0
  •   Chris Fulstow    14 年前

    你也许可以重复使用 MembershipProvider.EncryptPassword 方法,它依次使用 MachineKeySection 上课。