4

내 ASP.NET WebForms 응용 프로그램에서 (이 응용 프로그램은 Windows Server 2008 R2, IIS 7.5 및 런타임 v4.0 통합 모드 응용 프로그램 풀 그렇다면) 데이터를 암호화하고 QueryString에 넣고 System.Security.Cryptography.SymmetricAlgorithm 클래스를 사용하여 데이터를 해독합니다. 하지만 때때로 다음과 같은 예외가 발생하는 데이터 암호 해독에 몇 가지 문제가 있습니다.가끔 잘못된 문자열 오류를 해독하는 동안 오류가 발생했습니다 : System.Security.Cryptography.CryptographicException

Bad Data.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Security.Cryptography.CryptographicException: Bad Data.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[CryptographicException: Bad Data. ]
System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) +33
System.Security.Cryptography.Utils._DecryptData(SafeKeyHandle hKey, Byte[] data, Int32 ib, Int32 cb, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode PaddingMode, Boolean fDone) +0
System.Security.Cryptography.CryptoAPITransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) +313
System.Security.Cryptography.CryptoStream.FlushFinalBlock() +33 Cryptography35.SymmetricEncryptionUtility.DecryptData(Byte[] data, String keyFile) in E:\Documents\@Library\Cryptography35\Cryptography35\SymmetricEncryptionUtility.cs:124 Cryptography35.SymmetricQueryString.SymmetriclyEncryptedQueryString..ctor(String encryptedData, String keyfilename, String algorithmname) in E:\Documents\@Library\Cryptography35\Cryptography35\SymmetricQueryString\SymmetriclyEncryptedQueryString.cs:67 WebForms.Web.Views.purchase_a.GetSymmetriclyEncryptedQueryString() in E:\Documents\WebForms.Web\Views\purchase-a.aspx.cs:35 WebForms.Web.Views.purchase_a.Page_Load(Object sender, EventArgs e) in E:\Documents\WebForms.Web\Views\purchase-a.aspx.cs:56 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
System.Web.UI.Control.OnLoad(EventArgs e) +91
System.Web.UI.Control.LoadRecursive() +74 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207 Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version: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으로 리디렉션됩니다. 그것은 나에게 그 오류를 준다. 이제 오류의 원인을 찾았지만 어쨌든 그렇게해서는 안됩니다.

답변

-1

ECB에 암호화 및 암호 해독 모드를 설정하십시오.
rossum은 "ECB는 안전하지 않으며 정보가 유출됩니다"라고 말하면 파일에 임의로 액세스해야하는 경우 CTR을 사용하십시오.

+0

Don ' – rossum

3

당신은 버그가

당신은 암호 텍스트의 System.Text.Encoding 클래스 중 하나를 사용해서는 안 ... 코드에 숨어있다. 에 간헐적 인 오류가 발생합니다. Base64 인코딩과 System.Convert 클래스 메서드를 사용해야합니다.

  1. 암호화 된 바이트 []로부터 암호화 된 문자열을 얻으려면 사용해야 Convert.ToBase64String(byte[] bytes)

  2. 암호화 할 문자열에서 AA 원시 바이트 []를 얻기 위해 사용한다 : Convert.FromBase64String(string data)

내가 있었다 추가 정보를 위해, http://blogs.msdn.com/b/shawnfa/archive/2005/11/10/491431.aspx

0

에서 MS 보안 전문가 숀 Farkas 보낸 사람의 게시물을 참조하시기 바랍니다 다른 근본 원인, "잘못된 데이터"오류에 대해 "FlushFinalBlock"코드가없는 것과 관련이 있습니다. 이것은 완전히 암호화 된 값을 저장하지 않았기 때문에 분명히 문제를 일으켰습니다. 위의 코드 예에서 이지만 포함되어 있지만 코드에 묻어 있습니다. 나는 이것이 너무 주제에서 벗어나지 않기를 바란다. 그러나 나는 구글로부터이 게시물을 매우 빨리 발견 했으므로 다른 사람들이 여기에 와서 똑같은 실수를 범할 수도 있다고 가정한다.

@Dave Black 대답이 위에 게시 된 최종 코드와 관련이없는 것으로 언급 할 가치가 있습니다 ...? 위의 코드를 올바르게 읽었습니까? 시간이 지남에 따라 변경 될 수 있습니다. 그러나 이것은 내가 잘못 처리 한 항목을 정렬하려고 시도하는 데 약간의 타격을 줄 수 있습니다. (암호화 된 데이터를 올바르게 저장했는데, 전부는 아니지만 :-)

+0

@Orbonia, 나는 OP SymmetricEncryptionUtility 클래스의 EncryptData/DecryptData 메소드를 언급하고있었습니다 (현재 4/21/15 현재 존재 함). 원래 질문에서). –