我使用MachineKey.Protect()方法加密asp.net MVC应用程序中作为查询字符串传递的id。
下面是我用来加密/解密的代码:
public static string Encrypt(this string expression)
{
if (string.IsNullOrEmpty(expression))
return string.Empty;
byte[] stream = Encoding.Unicode.GetBytes(expression);
byte[] encodedValue = MachineKey.Protect(stream);
return HttpServerUtility.UrlTokenEncode(encodedValue);
}
public static string Decrypt(this string expression)
{
if (string.IsNullOrEmpty(expression))
return string.Empty;
byte[] stream = HttpServerUtility.UrlTokenDecode(expression);
byte[] decodedValue = MachineKey.Unprotect(stream);
return Encoding.Unicode.GetString(decodedValue);
}下面是我的MachineKey文件中的web.config元素:
<system.web>
.
.
.
<machineKey validationKey="xxx" decryptionKey="xxx" validation="SHA1" decryption="AES" />
</system.web>问题是加密的id不是持久的。每次我调用该方法时,我都会得到一个新的加密表达式。我怎样才能使它持久?
发布于 2014-08-16 20:57:24
摘要:
如果每次都想获得相同的结果,则需要使用不同的方法来保护数据。MachineKey.Protect每次运行都使用不同的IV,每次都会产生不同的结果。
细节
微软使许多点网框架的源代码可以在互联网上自由查看。
从顶部开始:MachineKey
保护方法使用AspNetCryptoServiceProvider
如果您通过AspNetCryptoServiceProvider.GetCryptoService执行代码到NetFXCryptoService,您将发现以下内容:
public byte[] Protect(byte[] clearData) {
// The entire operation is wrapped in a 'checked' block because any overflows should be treated as failures.
checked {
// These SymmetricAlgorithm instances are single-use; we wrap it in a 'using' block.
using (SymmetricAlgorithm encryptionAlgorithm = _cryptoAlgorithmFactory.GetEncryptionAlgorithm()) {
// Initialize the algorithm with the specified key and an appropriate IV
encryptionAlgorithm.Key = _encryptionKey.GetKeyMaterial();
if (_predictableIV) {
// The caller wanted the output to be predictable (e.g. for caching), so we'll create an
// appropriate IV directly from the input buffer. The IV length is equal to the block size.
encryptionAlgorithm.IV = CryptoUtil.CreatePredictableIV(clearData, encryptionAlgorithm.BlockSize);
}
else {
// If the caller didn't ask for a predictable IV, just let the algorithm itself choose one.
encryptionAlgorithm.GenerateIV();
}
byte[] iv = encryptionAlgorithm.IV;
using (MemoryStream memStream = new MemoryStream()) {
memStream.Write(iv, 0, iv.Length);
// At this point:
// memStream := IV
// Write the encrypted payload to the memory stream.
using (ICryptoTransform encryptor = encryptionAlgorithm.CreateEncryptor()) {
using (CryptoStream cryptoStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write)) {
cryptoStream.Write(clearData, 0, clearData.Length);
cryptoStream.FlushFinalBlock();
// At this point:
// memStream := IV || Enc(Kenc, IV, clearData)
// These KeyedHashAlgorithm instances are single-use; we wrap it in a 'using' block.
using (KeyedHashAlgorithm signingAlgorithm = _cryptoAlgorithmFactory.GetValidationAlgorithm()) {
// Initialize the algorithm with the specified key
signingAlgorithm.Key = _validationKey.GetKeyMaterial();
// Compute the signature
byte[] signature = signingAlgorithm.ComputeHash(memStream.GetBuffer(), 0, (int)memStream.Length);
// At this point:
// memStream := IV || Enc(Kenc, IV, clearData)
// signature := Sign(Kval, IV || Enc(Kenc, IV, clearData))
// Append the signature to the encrypted payload
memStream.Write(signature, 0, signature.Length);
// At this point:
// memStream := IV || Enc(Kenc, IV, clearData) || Sign(Kval, IV || Enc(Kenc, IV, clearData))
// Algorithm complete
byte[] protectedData = memStream.ToArray();
return protectedData;
}
}
}
}
}
}
}类是用默认选项初始化的,因此_predictableIV是假的。
因此,它每次都使用一个新的IV,这意味着每次都会有不同的结果,即使有相同的输入。
结果中包括IV,因此Unprotect方法可以逆转加密。
发布于 2014-08-12 22:00:29
尝试向Machine.Key.Proctect方法添加一个目的性参数!就像这样。
public static class Key
{
public static string EncryptWithAPurpose(this string expression, string[] purpose)
{
if (string.IsNullOrEmpty(expression))
return string.Empty;
byte[] stream = Encoding.Unicode.GetBytes(expression);
byte[] encodedValue = MachineKey.Protect(stream, purpose);
return HttpServerUtility.UrlTokenEncode(encodedValue);
}
public static string DecryptWithAPurpose(this string expression, string[] purpose)
{
if (string.IsNullOrEmpty(expression))
return string.Empty;
byte[] stream = HttpServerUtility.UrlTokenDecode(expression);
byte[] decodedValue = MachineKey.Unprotect(stream,purpose);
return Encoding.Unicode.GetString(decodedValue);
}
}用于测试:
{
public ActionResult GetKey(Guid id)
{
var vm = new vmGetKey();
vm.Guid = id;
//create a purpose
var purpose = new string[] { "Test", "WithAPurpose" };
//encrypt key1
vm.key1 = Key.EncryptWithAPurpose(id.ToString(), purpose);
//encrypt Key2
vm.key2 = Key.EncryptWithAPurpose(id.ToString(), purpose);
//decrypt key1
vm.key1_DecryptResult = Key.DecryptWithAPurpose(vm.key1, purpose);
//decrypt key2
vm.key2_DecryptResult = Key.DecryptWithAPurpose(vm.key2, purpose);
return View(vm);
}
public class vmGetKey
{
public Guid Guid { get; set; }
public string key1 { get; set; }
public string key2 { get; set; }
public string key1_DecryptResult { get; set; }
public string key2_DecryptResult { get; set; }
}
}

https://stackoverflow.com/questions/25206248
复制相似问题