利用ASP.NET machineKey加密我自己的数据
我想在ASP.NET MVC应用程序中加密一些数据,以防止用户篡改。我可以使用加密类进行实际的加密/解密,没有问题。主要的问题是找出加密密钥的存储位置并管理对它的更改利用ASP.NET machineKey加密我自己的数据,.net,asp.net,security,cryptography,.net,Asp.net,Security,Cryptography,我想在ASP.NET MVC应用程序中加密一些数据,以防止用户篡改。我可以使用加密类进行实际的加密/解密,没有问题。主要的问题是找出加密密钥的存储位置并管理对它的更改 由于ASP.NET已经为各种事情(ViewData encryption等)维护了machineKey,我想知道是否有任何ASP.NET函数可以让我使用machineKey对自己的数据进行加密/解密?这样我就不必设计自己的密钥管理系统了。我想不必直接设计。我不记得这是从哪里来的,可能是Reflector和一些博客的组合 publi
由于ASP.NET已经为各种事情(ViewData encryption等)维护了machineKey,我想知道是否有任何ASP.NET函数可以让我使用machineKey对自己的数据进行加密/解密?这样我就不必设计自己的密钥管理系统了。我想不必直接设计。我不记得这是从哪里来的,可能是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;
}
}
公共抽象类MyAwesomeClass
{
私有静态字节[]密钥;
专用静态MachineKeySection machineKeyConfig=
(机器钥匙部分)配置经理
.GetSection(“system.web/machineKey”);
//…剪断。。。
静态MyAwesomeClass()
{
字符串配置键;
字节[]键;
configKey=machineKeyConfig.DecryptionKey;
if(configKey.Contains(“自动生成”))
{
抛出新的ConfigurationErrorsException(
资源。MyAwesomeClass(需要明确的算法);
}
key=HexStringToByteArray(configKey);
cryptKey=密钥;
}
//…剪断。。。
受保护的静态字节[]加密(字节[]inputBuffer)
{
对称算法;
字节[]输出缓冲区;
如果(inputBuffer==null)
{
抛出新ArgumentNullException(“inputBuffer”);
}
算法=GetCryptAlgorithm();
使用(var ms=new MemoryStream())
{
GenerateIV()算法;
ms.Write(算法IV,0,算法IV.Length);
使用(var cs=newcryptostream)(
太太
算法。CreateEncryptor(),
CryptoStreamMode.Write)
{
cs.Write(inputBuffer,0,inputBuffer.Length);
cs.FlushFinalBlock();
}
outputBuffer=ms.ToArray();
}
返回输出缓冲区;
}
受保护的静态字节[]解密(字符串输入)
{
对称算法;
字节[]inputBuffer、inputVectorBuffer、outputBuffer;
如果(输入==null)
{
抛出新的ArgumentNullException(“输入”);
}
算法=GetCryptAlgorithm();
outputBuffer=null;
尝试
{
inputBuffer=Convert.FromBase64String(输入);
inputVectorBuffer=新字节[算法IV.Length];
数组。复制(
输入缓冲区,
输入向量缓冲区,
inputVectorBuffer.Length);
算法IV=inputVectorBuffer;
使用(var ms=new MemoryStream())
{
使用(var cs=newcryptostream)(
太太
算法。CreateDecryptor(),
CryptoStreamMode.Write)
{
写(
输入缓冲区,
inputVectorBuffer.Length,
inputBuffer.Length-inputVectorBuffer.Length);
cs.FlushFinalBlock();
}
outputBuffer=ms.ToArray();
}
}
捕获(格式化异常)
{
抛出新的加密异常(
“该字符串无法解码。”,e);
}
返回输出缓冲区;
}
//…剪断。。。
私有静态对称算法GetCryptAlgorithm()
{
对称算法;
字符串算法名;
algorithmName=machineKeyConfig.Decryption;
如果(algorithmName==“自动”)
{
抛出新的ConfigurationErrorsException(
资源。MyAwesomeClass(需要明确的算法);
}
开关(算法名称)
{
“AES”案:
算法=新的RijndaelManaged();
打破
案例“3DES”:
算法=新的TripleDESCryptoServiceProvider();
打破
“DES”案:
算法=新的DESCryptoServiceProvider();
打破
违约:
抛出新的ConfigurationErrorsException(
字符串格式(
CultureInfo.InvariantCulture,
Resources.MyAwesomeClass_无法识别的DalGorithmName,
算法名);
}
算法密钥=加密密钥;
返回算法;
}
私有静态字节[]HexStringToByteArray(字符串str)
{
字节[]缓冲区;
如果(str==null)
{
抛出新的ArgumentNullException(“str”);
}
如果(str.Length%2==1)
{
str='0'+str;
}
缓冲区=新字节[str.Length/2];
for(int i=0;i
警告买主 您可能能够重用该方法,而该方法反过来使用该类的一些(不幸的是内部)加密方法。ASP.NET 4.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;
}
}
}
更新:如前所述,请小心使用,否则可能会允许他人伪造表单身份验证令牌。如果使用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这样做是相当合理的。对于.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;
}
}