在我的ASP.NET WebForms应用程序中 (该应用程序在Windows Server 2008 R2,IIS 7.5和Runtime v4.0集成模式应用程序池上运行,如果重要的话) ,我正在加密数据,将其放在QueryString上并使用System.Security.Cryptography.SymmetricAlgorithm
类解密数据。但我偶尔遇到一些解密数据的问题,我得到以下异常;
糟糕的数据。
描述:未处理的异常 在执行期间发生 当前的网络请求。请查看 堆栈跟踪以获取更多信息 错误及其来源 代码。
异常详细信息: System.Security.Cryptography.CryptographicException: 糟糕的数据。
来源错误:
生成了未处理的异常 在执行当前 网络请求。有关的信息 异常的起源和位置 可以使用例外来识别 堆栈跟踪下面。
堆栈追踪:
[CryptographicException:错误的数据。 ]
System.Security.Cryptography.CryptographicException.ThrowCryptographicException(的Int32 hr)+33
System.Security.Cryptography.Utils._DecryptData(SafeKeyHandle hKey,Byte []数据,Int32 ib,Int32 cb, 字节[]&安培; outputBuffer,Int32 outputOffset,PaddingMode PaddingMode, 布尔fDone)+0
System.Security.Cryptography.CryptoAPITransform.TransformFinalBlock(字节[] inputBuffer,Int32 inputOffset,Int32 inputCount)+313
System.Security.Cryptography.CryptoStream.FlushFinalBlock() +33 Cryptography35.SymmetricEncryptionUtility.DecryptData(Byte [] data,String keyFile)in E:\文档\ @Library \ Cryptography35 \ Cryptography35 \ SymmetricEncryptionUtility.cs:124 Cryptography35.SymmetricQueryString.SymmetriclyEncryptedQueryString..ctor(字符串 encryptedData,String keyfilename, 字符串algorithmname) E:\文档\ @Library \ Cryptography35 \ Cryptography35 \ SymmetricQueryString \ SymmetriclyEncryptedQueryString.cs:67 WebForms.Web.Views.purchase_a.GetSymmetriclyEncryptedQueryString() 在 E:\文档\ WebForms.Web \查看\购a.aspx.cs:35 WebForms.Web.Views.purchase_a.Page_Load(对象 发件人,EventArgs e)in E:\文档\ WebForms.Web \查看\购a.aspx.cs:56 错误帮助(IntPtr的 fp,Object o,Object t,EventArgs e) +14 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object 发件人,EventArgs e)+35
System.Web.UI.Control.OnLoad(EventArgs的 e)+91
System.Web.UI.Control.LoadRecursive() +74 System.Web.UI.Page.ProcessRequestMain(布尔值 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());
}
}
更新 我想到了其他的东西。在我的一个页面上,我正在做以下事情;
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
并繁荣。它给了我那个错误。好吧,我现在找到了错误的来源,但不管怎么说都不应该发生。
答案 0 :(得分:3)
您的代码中隐藏着一个错误...
您绝不应将任何System.Text.Encoding类用于密文。您将遇到间歇性错误。您应该使用Base64编码和System.Convert类方法。
要从加密字节[]获取加密字符串,您应该使用:Convert.ToBase64String(byte[] bytes)
要从要加密的字符串中获取原始字节[],您应该使用:Convert.FromBase64String(string data)
有关其他信息,请参阅MS安全大师Shawn Farkas的帖子http://blogs.msdn.com/b/shawnfa/archive/2005/11/10/491431.aspx
答案 1 :(得分:0)
我有一个不同的根本原因,因为“Bad Data”错误,这与没有“FlushFinalBlock”代码有关。这显然导致了一个问题,因为我从未存储完全加密的值。 现在在上面的代码示例中包含 ,但显然它隐藏在代码中。我希望这不是太偏离主题,但我确实很快就从Google发现了这篇文章,所以我认为其他人也可能会来到这里并犯同样的错误。
也许值得一提的是@Dave Black答案似乎与上面公布的最终代码无关......?我是否正确阅读了上述代码? 这可能是随着时间的推移而发生变化的结果 - 但这使我在尝试解决出错的方面(我已经正确存储了我的加密数据,而不是所有这些:-()
答案 2 :(得分:-1)
将加密和解密模式设置为ECB 正如rossum所说:“ECB不安全,它会泄露信息”,所以如果您需要随机访问您的文件,请使用CTR。