C# 当代码无法解密时,如何防止异常?

C# 当代码无法解密时,如何防止异常?,c#,encryption,aes,C#,Encryption,Aes,我有一个公共web钩子,服务正在调用它来发送我的网站通知。在这个web钩子中,我期待一个加密的令牌。当我获得令牌时,我使用预定义的密钥对其进行解密,并检查令牌是否符合我的预期。这个很好用 当一个未加密或错误的令牌被传递到函数中时,解密当然会失败。这没关系,但我不希望在发生这种情况时生成异常。如果某个黑客在一秒钟内针对我的web钩子创建1000000个错误请求,并且每个请求需要1秒来处理一个巨大的异常,那么它将使我的服务器崩溃 以下是我目前的解密代码: public static string D

我有一个公共web钩子,服务正在调用它来发送我的网站通知。在这个web钩子中,我期待一个加密的令牌。当我获得令牌时,我使用预定义的密钥对其进行解密,并检查令牌是否符合我的预期。这个很好用

当一个未加密或错误的令牌被传递到函数中时,解密当然会失败。这没关系,但我不希望在发生这种情况时生成异常。如果某个黑客在一秒钟内针对我的web钩子创建1000000个错误请求,并且每个请求需要1秒来处理一个巨大的异常,那么它将使我的服务器崩溃

以下是我目前的解密代码:

public static string Decrypt(string cipherText, string key)
    {
        string EncryptionKey = key;
        cipherText = cipherText.Replace(" ", "+");

        //I added this to prevent exception when trying to Convert.FromBase64String()
        if (cipherText.Length % 4 != 0)
        {
            //cipherText must be a length that is a multiple of 4, otherwise it will fail
            return null;
        }

        byte[] cipherBytes = Convert.FromBase64String(cipherText);
        using (Aes encryptor = Aes.Create())
        {
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
            encryptor.Key = pdb.GetBytes(32);
            encryptor.IV = pdb.GetBytes(16);
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(cipherBytes, 0, cipherBytes.Length);
                    cs.Close();  //currently giving exception HERE
                }
                cipherText = Encoding.Unicode.GetString(ms.ToArray());
            }
        }
        return cipherText;
    }
它在cs.Close()
上给了我一个异常,当我有意传入一个非加密字符串时,输入数据不是一个完整的块。我不确定这里到底检查了什么,所以我不知道如何预防


如何重构此代码,以便在字符串无法解密时不会引发异常?

您可以
捕获
异常并根据需要处理它。(记录、重新路由、忽略等)。Try/catch文档可以在这里找到:

您可以
捕获
异常并根据需要处理它。(记录、重新路由、忽略等)。可以在此处找到Try/catch文档:

当您使用未经身份验证的模式(如CBC)解密密文时,填充错误可能检测到错误的密钥或错误的最终块,概率约为255倍或256倍。当最后一个块损坏并且找不到有效的填充时,就会发生这种情况。默认情况下使用,并且它具有可验证的特殊结构

您可以请求解密器不要尝试以任何方式取消添加:

encryptor.Padding = PaddingMode.None;
但是您需要自己取消填充(AES的填充字节只能在1到16之间):

var ctBytes=ms.ToArray();
var last=ctBytes[ctBytes.Length-1];
如果(最后一次<17&&last>0){
cipherText=Encoding.Unicode.GetString(ctBytes.Take(ctBytes.Length-last));
}否则{
密文=空;
}

当您使用CBC等未经身份验证的模式解密密文时,填充错误可能检测到错误的密钥或错误的最终块,其概率约为255倍或256倍。当最后一个块损坏并且找不到有效的填充时,就会发生这种情况。默认情况下使用,并且它具有可验证的特殊结构

您可以请求解密器不要尝试以任何方式取消添加:

encryptor.Padding = PaddingMode.None;
但是您需要自己取消填充(AES的填充字节只能在1到16之间):

var ctBytes=ms.ToArray();
var last=ctBytes[ctBytes.Length-1];
如果(最后一次<17&&last>0){
cipherText=Encoding.Unicode.GetString(ctBytes.Take(ctBytes.Length-last));
}否则{
密文=空;
}

我认为您需要确保您的
密码字节
长度可被
加密程序.BlockSize
整除。如果您实际上正试图处理数据流,这可能会很烦人。但是如果你只是获取一个字符串,这应该不是问题。如果你让一个黑客创建1000000个错误请求,但仍然没有采取任何措施阻止他,那么你已经犯了严重错误。我认为你需要确保你的
密码字节
长度可以被
加密器.BlockSize
整除。如果您实际上正试图处理数据流,这可能会很烦人。但是,如果你只是获取一个字符串,这应该不是问题。如果你让一个黑客创建1000000个错误请求,但仍然没有采取任何措施阻止他,那么你已经犯了严重错误。我知道try/catch,但我认为如果我“捕获”了异常,那么它并不能解决我的问题“如果某个黑客在一秒钟内针对我的web钩子创建1000000个错误请求,并且每个请求需要1秒来处理一个巨大的异常,那么它将使我的服务器崩溃。“??@Albatrossafe这是正确的处理方法。当然,您可以破坏crypto API,自己处理事情,这样它就不会抛出异常,但接下来您将进入更危险的领域:(重新)实现加密。这更糟糕。只需像您应该的那样处理异常,并实施一些速率限制来防止您描述的场景。我知道try/catch,但我认为如果我“捕获”异常,那么它并不能解决我的问题“如果某个黑客在一秒钟内针对我的web钩子创建1000000个错误请求,并且每个请求需要1秒来处理一个巨大的异常,那么它将使我的服务器崩溃。“??@Albatrossafe这是正确的处理方法。当然,您可以破坏crypto API,自己处理事情,这样它就不会抛出异常,但接下来您将进入更危险的领域:(重新)实现加密。这更糟糕。只需像您应该的那样处理异常,并实现一些速率限制,以防止您描述的场景。