В моем приложении ASP.NET WebForms (приложение работает на Windows Server 2008 R2, IIS 7.5 и Runtime v4.0 в интегрированном режиме, если это имеет значение) , I Я шифрую данные, помещаю их в QueryString и дешифрую, используя класс System.Security.Cryptography.SymmetricAlgorithm
. Но у меня иногда возникают проблемы с расшифровкой данных, которые я получаю в следующем исключении:
Плохие данные.
Описание: необработанное исключение
произошло во время исполнения
текущий веб-запрос. Пожалуйста, просмотрите
трассировка стека для получения дополнительной информации о
ошибка и откуда она возникла
код.
Сведения об исключении:
System.Security.Cryptography.CryptographicException:
Неверные данные.
Ошибка источника:
Создано необработанное исключение
во время исполнения текущего
веб-запрос. Информация относительно
Происхождение и место исключения
можно определить с помощью исключения
трассировка стека ниже.
Трассировка стека:
[CryptographicException: неверные данные. ]
System.Security.Cryptography.CryptographicException.ThrowCryptographicException (Int32
ч) + 33
System.Security.Cryptography.Utils._DecryptData (SafeKeyHandle
данные hKey, Byte [], Int32 ib, Int32 cb,
Byte [] & outputBuffer, Int32
outputOffset, PaddingMode PaddingMode,
Boolean fDone) + 0
System.Security.Cryptography.CryptoAPITransform.TransformFinalBlock (байт []
inputBuffer, Int32 inputOffset, Int32
inputCount) + 313
System.Security.Cryptography.CryptoStream.FlushFinalBlock ()
+33 Криптография35.SymmetricEncryptionUtility.DecryptData (Byte []
data, String keyFile) в
E: \ Documents \ @Library \ Cryptography35 \ Cryptography35 \ SymmetricEncryptionUtility.cs: 124
Cryptography35.SymmetricQueryString.SymmetriclyEncryptedQueryString..ctor (String
encryptedData, String keyfilename,
Строковое имя алгоритма) в
E: \ Documents \ @Library \ Cryptography35 \ Cryptography35 \ SymmetricQueryString \ SymmetriclyEncryptedQueryString.cs: 67
WebForms.Web.Views.purchase_a.GetSymmetriclyEncryptedQueryString ()
в
E: \ Documents \ WebForms.Web \ Views \ покупного a.aspx.cs: 35
WebForms.Web.Views.purchase_a.Page_Load (Объект
отправитель, EventArgs e) в
E: \ Documents \ WebForms.Web \ Views \ покупного a.aspx.cs: 56
System.Web.Util.CalliHelper.EventArgFunctionCaller (IntPtr
fp, объект o, объект t, EventArgs e)
+14 System.Web.Util.CalliEventHandlerDelegateProxy.Callback (Object
отправитель, EventArgs e) + 35
System.Web.UI.Control.OnLoad (EventArgs
д) + 91
System.Web.UI.Control.LoadRecursive ()
+74 System.Web.UI.Page.ProcessRequestMain (Boolean
includeStagesBeforeAsyncPoint, Boolean
includeStagesAfterAsyncPoint) +2207
Информация о версии: Microsoft .NET Framework Версия: 4.0.30319;
ASP.NET версия: 4.0.30319.1
Как я уже говорил, я получаю эту ошибку иногда, а не каждый раз, когда запускаю ее. Я не знаю, где я делаю это неправильно (на этапе шифрования или дешифрования) Вот код, который я использовал для этого;
private SymmetriclyEncryptedQueryString GetSymmetriclyEncryptedQueryString() {
#region _decrypting the value
string KeyFileName;
string AlgorithmName = "DES";
Cryptography35.SymmetricEncryptionUtility.AlgorithmName = AlgorithmName;
KeyFileName = HttpContext.Current.Server.MapPath("~/@config/") + "\\symmetric_key.config";
#endregion
#region _reading and assigning the value
if (Request.QueryString["q"] == null)
throw new NullReferenceException("QueryString value is null on search result page");
SymmetriclyEncryptedQueryString QueryString = new SymmetriclyEncryptedQueryString(Request.QueryString["q"], KeyFileName, AlgorithmName);
#endregion
return QueryString;
}
SymmetriclyEncryptedQueryString
Класс
public class SymmetriclyEncryptedQueryString : System.Collections.Specialized.StringDictionary {
public string KeyFileName { get; set; }
public string AlgorithmName { get; set; }
/// <summary>
/// Use this for encrypte the value
/// </summary>
/// <param name="keyfilename"></param>
/// <param name="algorithmname"></param>
public SymmetriclyEncryptedQueryString(string keyfilename, string algorithmname) {
KeyFileName = keyfilename;
AlgorithmName = algorithmname;
}
/// <summary>
/// Use this for decrypte the value.
/// </summary>
/// <param name="encryptedData"></param>
/// <param name="keyfilename"></param>
/// <param name="algorithmname"></param>
public SymmetriclyEncryptedQueryString(string encryptedData, string keyfilename, string algorithmname) {
#region _initials
KeyFileName = keyfilename;
AlgorithmName = algorithmname;
if (String.IsNullOrEmpty(AlgorithmName)){
SymmetricEncryptionUtility.AlgorithmName = AlgorithmName;
}
else{
SymmetricEncryptionUtility.AlgorithmName = "DES";
}
SymmetricEncryptionUtility.ProtectKey = false;
// Check for encryption key
if (!File.Exists(KeyFileName)){
throw new FileNotFoundException("Keyfilename for SymmetriclyEncryptedQueryString is not found on '" + KeyFileName + "'!");
}
#endregion
//Arrange the data
//In order not to get following exception
//Invalid length for a Base-64 char array.
//byte[] RawData = Convert.FromBase64String(encryptedData);
encryptedData = encryptedData.Replace(" ", "+");
int mod4 = encryptedData.Length % 4;
if (mod4 > 0)
encryptedData += new string('=', 4 - mod4);
// Decrypt data passed in
byte[] RawData = Convert.FromBase64String(encryptedData);
string DecryptedVal = SymmetricEncryptionUtility.DecryptData(RawData, KeyFileName);
string StringData = DecryptedVal;
// Split the data and add the contents
int Index;
string[] SplittedData = StringData.Split(new char[] { '&' });
foreach (string SingleData in SplittedData) {
Index = SingleData.IndexOf('=');
base.Add(
HttpUtility.UrlDecode(SingleData.Substring(0, Index)),
HttpUtility.UrlDecode(SingleData.Substring(Index + 1))
);
}
}
public override string ToString() {
#region _initials
if (String.IsNullOrEmpty(AlgorithmName)) {
SymmetricEncryptionUtility.AlgorithmName = AlgorithmName;
} else {
SymmetricEncryptionUtility.AlgorithmName = "DES";
}
SymmetricEncryptionUtility.ProtectKey = false;
// Check for encryption key
if (!File.Exists(KeyFileName)) {
throw new FileNotFoundException("Keyfilename for AsymmetriclyEncryptedQueryString is not found on '" + KeyFileName + "'!");
}
#endregion
#region _prepare for querystring
// Go through the contents and build a
// typical query string
StringBuilder Content = new StringBuilder();
foreach (string key in base.Keys) {
Content.Append(HttpUtility.UrlEncode(key));
Content.Append("=");
Content.Append(HttpUtility.UrlEncode(base[key]));
Content.Append("&");
}
// Remove the last '&'
Content.Remove(Content.Length - 1, 1);
#endregion
#region _encrypt the contents
// Now encrypt the contents
byte[] data = SymmetricEncryptionUtility.EncryptData(Content.ToString(), KeyFileName);
string EncryptedVal = Convert.ToBase64String(data);
#endregion
return EncryptedVal;
}
}
SymmetricEncryptionUtility
Класс
public static class SymmetricEncryptionUtility {
private static bool _ProtectKey;
private static string _AlgorithmName;
// Shhh!!! Don't tell anybody!
private const string MyKey = "m$%&kljasldk$%/65asjdl";
public static string AlgorithmName {
get { return _AlgorithmName; }
set { _AlgorithmName = value; }
}
public static bool ProtectKey {
get { return _ProtectKey; }
set { _ProtectKey = value; }
}
public static void GenerateKey(string targetFile) {
// Create the algorithm
SymmetricAlgorithm Algorithm = SymmetricAlgorithm.Create(AlgorithmName);
Algorithm.GenerateKey();
// No get the key
byte[] Key = Algorithm.Key;
if (ProtectKey)
{
// Use DPAPI to encrypt key
Key = ProtectedData.Protect(
Key, null, DataProtectionScope.LocalMachine);
}
// Store the key in a file called key.config
using (FileStream fs = new FileStream(targetFile, FileMode.Create))
{
fs.Write(Key, 0, Key.Length);
}
}
public static void ReadKey(SymmetricAlgorithm algorithm, string keyFile)
{
byte[] Key;
using (FileStream fs = new FileStream(keyFile, FileMode.Open))
{
Key = new byte[fs.Length];
fs.Read(Key, 0, (int)fs.Length);
}
if (ProtectKey)
algorithm.Key = ProtectedData.Unprotect(Key, null, DataProtectionScope.LocalMachine);
else
algorithm.Key = Key;
}
public static byte[] EncryptData(string data, string keyFile)
{
// Convert string data to byte array
byte[] ClearData = Encoding.UTF8.GetBytes(data);
// Now Create the algorithm
SymmetricAlgorithm Algorithm = SymmetricAlgorithm.Create(AlgorithmName);
ReadKey(Algorithm, keyFile);
// Encrypt information
MemoryStream Target = new MemoryStream();
// Append IV
Algorithm.GenerateIV();
Target.Write(Algorithm.IV, 0, Algorithm.IV.Length);
// Encrypt actual data
CryptoStream cs = new CryptoStream(Target, Algorithm.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(ClearData, 0, ClearData.Length);
cs.FlushFinalBlock();
// Output the bytes of the encrypted array to the textbox
return Target.ToArray();
}
public static string DecryptData(byte[] data, string keyFile) {
// Now create the algorithm
SymmetricAlgorithm Algorithm = SymmetricAlgorithm.Create(AlgorithmName);
ReadKey(Algorithm, keyFile);
// Decrypt information
MemoryStream Target = new MemoryStream();
// Read IV
int ReadPos = 0;
byte[] IV = new byte[Algorithm.IV.Length];
Array.Copy(data, IV, IV.Length);
Algorithm.IV = IV;
ReadPos += Algorithm.IV.Length;
CryptoStream cs = new CryptoStream(Target, Algorithm.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(data, ReadPos, data.Length - ReadPos);
cs.FlushFinalBlock();
// Get the bytes from the memory stream and convert them to text
return Encoding.UTF8.GetString(Target.ToArray());
}
}
UPDATE
Я понял что-то еще. На одной из моих страниц я делаю следующее:
protected override void OnInit(EventArgs e) {
string url = Request.Url.AbsoluteUri.ToLower();
if (url.StartsWith("http:"))
{
Response.Redirect(url.Replace("http://", "https://"), true);
}
}
Я понял, что это вызывает проблему. (Помните, что мои зашифрованные данные находятся внутри строки запроса), когда я пытаюсь перейти на эту страницу с http
, и она перенаправляет ее на https
и boom. это дает мне эту ошибку. Хорошо, теперь я нашел источник ошибки, но это все равно не должно происходить.