5

私の ASP.NET WebForms アプリ(アプリは Windows Server 2008 R2、IIS 7.5、およびランタイム v4.0 統合モード アプリ プールで実行されています)では、データを暗号化し、それを QueryString に配置し、System.Security.Cryptography.SymmetricAlgorithmクラスを使用してデータを復号化しています。しかし、次の例外が発生しているデータの復号化で問題が発生することがあります。

不良データ。

説明: 現在の Web 要求の実行中に未処理の例外が発生しました。エラーの詳細とコード内のどこでエラーが発生したかについては、スタック トレースを確認してください。

例外の詳細: System.Security.Cryptography.CryptographicException: 不正なデータです。

ソース エラー:

現在の Web 要求の実行中に未処理の例外が生成されました。例外の発生元と場所に関する情報は、以下の例外スタック トレースを使用して特定できます。

スタックトレース:

[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(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(オブジェクト送信者、EventArgs e) E:\Documents\WebForms.Web\Views\purchase-a.aspx.cs :56 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp、オブジェクト o、オブジェクト t、EventArgs e) +14 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(オブジェクト送信者、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 バージョン情報: Microsoft .NET フレームワーク バージョン: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());
    }

}

更新 私は何か他のものを考え出した。私のページの1つで、次のことを行っています。

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、ブームになります。それは私にそのエラーを与えます。さて、エラーの原因を見つけましたが、とにかく発生するべきではありません。

4

3 に答える 3

3

コードにバグが潜んでいます...

System.Text.Encoding クラスを暗号化テキストに使用しないでください。断続的なエラーが発生します。Base64 エンコーディングと System.Convert クラス メソッドを使用する必要があります。

  1. 暗号化された byte[] から暗号化された文字列を取得するには、次を使用する必要があります。Convert.ToBase64String(byte[] bytes)

  2. 暗号化する文字列から raw byte[] を取得するには、次を使用する必要があります。Convert.FromBase64String(string data)

詳細については、MS セキュリティの第一人者である Shawn Farkas の投稿 ( http://blogs.msdn.com/b/shawnfa/archive/2005/11/10/491431.aspx ) を参照してください。

于 2011-12-30T18:34:12.463 に答える
0

「Bad Data」エラーの別の根本原因があり、それは「FlushFinalBlock」コードがないことに関連していました。完全に暗号化された値を保存したことがないため、これは明らかに問題を引き起こしました。上記のコード例にはそれ含まれていますが、明らかにコードに埋め込まれています。これがあまり話題から外れていないことを願っていますが、Google からこの投稿をかなり早く見つけたので、他の人がここに来て同じ単純な間違いを犯す可能性があると思います.

@Dave Blackの回答は、上記の最終コードに関連していないように見えることにも言及する価値があるかもしれません...? 上記のコードを正しく読みましたか? これは、時間の経過に伴う変更の結果である可能性があります-しかし、これにより、何がうまくいかなかったのかを整理しようとする際に少し迷いました(すべてではなく、暗号化されたデータを正しく保存しました:-()

于 2012-11-12T14:51:51.213 に答える
-1

暗号化および復号化モードを ECB に設定します。
rossum が言うように、「ECB は安全ではありません。情報が漏洩します」。ファイルへのランダム アクセスが必要な場合は、CTR を使用します。

于 2011-07-04T18:35:09.133 に答える