2

私のウェブサイトには次のコードがあります。URL クエリを commandencrypted という名前の文字列として受け取ります。暗号化されたコマンドをメモリストリームにコピーし、それを解読して文字列に戻す try/catch/finally ブロックがあります。try ブロックでエラーが発生した場合は、catch ブロックで処理されます。ただし、使用されるすべてのリソースが finally ブロックで閉じられていることを確認したいと考えています。無効な URL クエリ コマンドが提供されると、csencryptedcommand CryptoStream を閉じようとしているときに例外が発生します。コードの後に​​例外の詳細が続きます。

    // Resources used for storing and decrypting the encrypted client command
    MemoryStream msencryptedcommand = null;
    RijndaelManaged rmencryptedcommand = null;
    CryptoStream csencryptedcommand = null;
    StreamReader srdecryptedcommand = null;
    MemoryStream msdecryptedcommand = null;

    try
    {
        // Copy the encrypted client command (where two characters represent a byte) to a memorystream
        msencryptedcommand = new MemoryStream();
        for (int i = 0; i < encryptedcommand.Length; )
        {
            msencryptedcommand.WriteByte(Byte.Parse(encryptedcommand.Substring(i, 2), NumberStyles.HexNumber));
            i = i + 2;
        }
        msencryptedcommand.Flush();
        msencryptedcommand.Position = 0;

        // Define parameters used for decryption
        byte[] key = new byte[] { //bytes hidden// };
        byte[] iv = new byte[] { //bytes hidden// };
        rmencryptedcommand = new RijndaelManaged();
        csencryptedcommand = new CryptoStream(msencryptedcommand, rmencryptedcommand.CreateDecryptor(key, iv), CryptoStreamMode.Read);
        msdecryptedcommand = new MemoryStream();

        // Decrypt the client command
        int decrytptedbyte;
        while ((decrytptedbyte = csencryptedcommand.ReadByte()) != -1)
        {
            msdecryptedcommand.WriteByte((byte)decrytptedbyte);
        }

        // Store the decrypted client command as a string
        srdecryptedcommand = new StreamReader(msdecryptedcommand);
        srdecryptedcommand.BaseStream.Position = 0;
        string decryptedcommand = srdecryptedcommand.ReadToEnd();
    }
    catch (Exception ex)
    {
        ErrorResponse("Invalid URL Query", context, ex.ToString());
        return;
    }
    finally
    {
        // If any resources were used, close or clear them
        if (srdecryptedcommand != null)
        {
            srdecryptedcommand.Close();
        }

        if (msdecryptedcommand != null)
        {
            msdecryptedcommand.Close();
        }

        if (csencryptedcommand != null)
        {
            csencryptedcommand.Close();
        }

        if (rmencryptedcommand != null)
        {
            rmencryptedcommand.Clear();
        }

        if (msencryptedcommand != null)
        {
            msencryptedcommand.Close();
        }
    }

次の未処理の例外が発生しました: System.Security.Cryptography.CryptographicException: 復号化するデータの長さが無効です。System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock (Byte[] inputBuffer、Int32 inputOffset、Int32 inputCount) で System.Security.Cryptography.CryptoStream.FlushFinalBlock() で System.Security.Cryptography.CryptoStream.Dispose (ブール値破棄) で System. System.Web.HttpApplication の System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() の update.ashx:line 92 の dongleupdate.ProcessRequest(HttpContext context) の .IO.Stream.Close()。 ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) URL リファラー: ユーザー エージェント: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (Gecko のような KHTML) Chrome/30.0.1599.69 Safari/537.

編集:

using ステートメントを使用するようにコードを変更しました。これは、すべてのリソースが閉じられていることを確認する有効な方法でもありますか?

    try
    {
        // Copy the encrypted client command (where two characters represent a byte) to a memorystream
        using (MemoryStream msencryptedcommand = new MemoryStream())
        {
            for (int i = 0; i < encryptedcommand.Length; )
            {
                msencryptedcommand.WriteByte(Byte.Parse(encryptedcommand.Substring(i, 2), NumberStyles.HexNumber));
                i = i + 2;
            }
            msencryptedcommand.Flush();
            msencryptedcommand.Position = 0;

            // Define parameters used for decryption
            byte[] key = new byte[] { //bytes hidden// };
            byte[] iv = new byte[] { //bytes hidden// };
            using (RijndaelManaged rmencryptedcommand = new RijndaelManaged())
            {
                using (CryptoStream csencryptedcommand = new CryptoStream(msencryptedcommand, rmencryptedcommand.CreateDecryptor(key, iv), CryptoStreamMode.Read))
                {
                    using (MemoryStream msdecryptedcommand = new MemoryStream())
                    {

                        // Decrypt the client command
                        int decrytptedbyte;
                        while ((decrytptedbyte = csencryptedcommand.ReadByte()) != -1)
                        {
                            msdecryptedcommand.WriteByte((byte)decrytptedbyte);
                        }

                        // Store the decrypted client command as a string
                        using (StreamReader srdecryptedcommand = new StreamReader(msdecryptedcommand))
                        {
                            srdecryptedcommand.BaseStream.Position = 0;
                            string decryptedcommand = srdecryptedcommand.ReadToEnd();
                        }
                    }
                }
            }
        }
    }
    catch (Exception ex)
    {
        ErrorResponse("Invalid URL Query", context, ex.ToString());
        return;
    }
4

2 に答える 2

5

CryptoStreamあなたをブロックでラップすると、次のusingように自動的に閉じられ、 を介して破棄されますDispose Pattern

using(csencryptedcommand = new CryptoStream(msencryptedcommand, 
    rmencryptedcommand.CreateDecryptor(key, iv), CryptoStreamMode.Read))
{
    // Do things with crypto stream here
}

詳細については、ステートメントの使用 (C# リファレンス)のドキュメントを参照してください。

アップデート:

Reflectorを使用したCryptoStreamDisposeメソッドのコードは次のとおりです。

protected override void Dispose(bool disposing)
{
    try
    {
        if (disposing)
        {
            if (!this._finalBlockTransformed)
            {
                this.FlushFinalBlock();
            }
            this._stream.Close();
        }
    }
    finally
    {
        try
        {
            this._finalBlockTransformed = true;
            if (this._InputBuffer != null)
            {
                Array.Clear(this._InputBuffer, 0, this._InputBuffer.Length);
            }
            if (this._OutputBuffer != null)
            {
                Array.Clear(this._OutputBuffer, 0, this._OutputBuffer.Length);
            }
            this._InputBuffer = null;
            this._OutputBuffer = null;
            this._canRead = false;
            this._canWrite = false;
        }
        finally
        {
            base.Dispose(disposing);
        }
    }
}

注: ご覧のとおり、次の行を介してストリームを閉じる明示的な呼び出しがあります。

this._stream.Close();
于 2013-10-16T16:19:07.673 に答える
0

あなたが使用しているすべてのオブジェクトは IDisposable を実装していると思うので、もし私があなただったら、それらすべてを using ステートメントでラップして、自動的にクリーンアップされるようにします。

using(msencryptedcommand = new MemoryStream())
{
    ....
}
于 2013-10-16T16:20:11.140 に答える