微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

.net – 解密字符串时偶尔出现错误数据错误:System.Security.Cryptography.CryptographicException

在我的ASP.NET WebForms应用程序中(该应用程序在 Windows Server 2008 R2,IIS 7.5和运行时v4.0集成模式应用程序池上运行,如果它很重要),我正在加密数据,将其放在QueryString上并使用System解密数据. Security.Cryptography.SymmetricAlgorithm类.但我偶尔遇到一些解密数据的问题,我得到以下异常;

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,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,(int)fs.Length);
        }

        if (ProtectKey)
            algorithm.Key = ProtectedData.Unprotect(Key,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,Algorithm.IV.Length);

        // Encrypt actual data
        CryptoStream cs = new CryptoStream(Target,Algorithm.CreateEncryptor(),CryptoStreamMode.Write);
        cs.Write(ClearData,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和繁荣.它给了我那个错误.好吧,我现在找到了错误的来源,但不管怎么说都不应该发生.

解决方法

您的代码中隐藏着一个错误

永远不要将任何System.Text.Encoding类用于密文.您将遇到间歇性错误.您应该使用Base64编码和System.Convert类方法.

>要从加密的byte []获取加密字符串,您应该使用:Convert.ToBase64String(byte [] bytes)
>要从要加密的字符串中获取原始byte [],您应该使用:Convert.FromBase64String(string data)

有关其他信息,请参阅MS Security大师Shawn Farkas在http://blogs.msdn.com/b/shawnfa/archive/2005/11/10/491431.aspx的帖子

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐