Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用AES/CBC/NoPadding算法解密字符串_C#_Visual Studio 2012_Windows Phone 8_Encryption_Aes - Fatal编程技术网

C# 使用AES/CBC/NoPadding算法解密字符串

C# 使用AES/CBC/NoPadding算法解密字符串,c#,visual-studio-2012,windows-phone-8,encryption,aes,C#,Visual Studio 2012,Windows Phone 8,Encryption,Aes,我想在c#Windows Phone 8应用程序中使用AES/CBC/Nopadding解密加密的Sting。我的字符串位于IsolatedSorage的文件中。我贴了一条破烂的绳子 由此,我使用类来解密。 但是如何将填充设置为NoPadding,因为默认情况下,填充设置为PKCS7 编辑1: 当我在第一线解密加密字符串时 byte[] data = Convert.FromBase64String(dataToDecrypt); 移动到最后一个block并获取异常,输入不是有效的Base-

我想在c#Windows Phone 8应用程序中使用
AES/CBC/Nopadding
解密加密的Sting。我的字符串位于
IsolatedSorage
的文件中。我贴了一条破烂的绳子

由此,我使用类来解密。 但是如何将填充设置为
NoPadding
,因为默认情况下,填充设置为
PKCS7

编辑1:

当我在第一线解密加密字符串时

 byte[] data = Convert.FromBase64String(dataToDecrypt);
移动到
最后一个block
并获取
异常,输入不是有效的Base-64字符串,因为它包含非Base-64字符、两个以上的填充字符,或者解密字符串中的填充字符中包含非法字符。

这有点让人困惑,因为windows phone支持对这个类进行解密

若我完全错了,建议我提供有关Windows Phone中算法的文章的url

编辑2:

正如下面的回答所暗示的,“我得到的是以字节为单位的cyperText,它在解密端是好的,但它给出了一个描述例外

       [Cryptography_SSD_InvalidDataSize]
    Arguments: 
    Debugging resource strings are unavailable. Often the key and arguments provide 
sufficient information to diagnose the problem
我认为问题在于IV[盐键]或将填充设置为AesManged。 但我无法在Windows Phone中将padding属性更改为。
默认情况下,AesManged的填充为
PKCS7
。我想更改为
NoPadding
。因为我的cyperText是使用AES/CBC/NoPadding算法加密的“

链接到的字符串不是Base-64。它看起来像是原始加密字节,被解释为字符。要么在加密端工作以输出原始字节的Base-64字符串编码,要么在解密端工作以原始字节而不是文本的形式读取密码文本,忘记删除Base-64


一般来说,在加密端工作会更好,因为传递Base-64文本比传递原始字节更容易出错。

如果我理解这个问题,您的数据已经在AES CBC模式下加密,没有填充。但是在你想要解密数据的手机上,你唯一的选择就是PKCS#7填充

你真走运!您可以使用PKCS#7填充对密文进行解密。你所需要做的就是在手机上的密文中添加填充,然后解密

要在事实之后添加填充,您需要加密一小段数据并将其附加到密文中。然后,你解密修改后的密文,去掉一小段数据,就得到了原始的明文

以下是您的操作方法:

  • 在电话里用密文。这是16字节的倍数,即使没有填充。没有其他可能——AES密文总是16字节的倍数

  • 将密文的最后16个字节放在一边,并将其设置为AES加密的IV。(加密,而不是解密。)使用与稍后解密时使用的密钥相同的密钥

  • 现在加密小于16字节的内容,例如字符“$”。这部手机将添加PKCS#7填充

  • 将生成的16个字节的密文追加到步骤1中的原始密文中,现在就有了一个正确的PKCS#7填充密文,其中包括原始明文加上添加的“$”

  • 使用原始IV和相同的密钥,现在解密此组合密文。现在,您可以删除将显示在纯文本末尾的“$”(或在步骤3中添加的任何内容)

  • 当使用原始密文的最后16个字节对小段进行加密时,实际上您是在真正的AES CBC模式下扩展密文,而您恰好是在使用PKCS#7填充进行扩展,因此您现在可以解密整个内容并去掉小段。您将获得没有填充的原始纯文本

    我认为在代码中显示这一点会很有趣:

    var rfc2898 = new Rfc2898DeriveBytes("password", new byte[8]);
    
    using (var aes = new AesManaged())
    {
        aes.Key = rfc2898.GetBytes(32);
        aes.IV = rfc2898.GetBytes(16);
    
        var originalIV = aes.IV; // keep a copy
    
        // Prepare sample plaintext that has no padding
        aes.Padding = PaddingMode.None;
        var plaintext = Encoding.UTF8.GetBytes("this plaintext has 32 characters");
        byte[] ciphertext;
        using (var encryptor = aes.CreateEncryptor())
        {
            ciphertext = encryptor.TransformFinalBlock(plaintext, 0, plaintext.Length);
            Console.WriteLine("ciphertext: " + BitConverter.ToString(ciphertext));
        }
    
        // From this point on we do everything with PKCS#7 padding
        aes.Padding = PaddingMode.PKCS7;
    
        // This won't decrypt -- wrong padding
        try
        {
            using (var decryptor = aes.CreateDecryptor())
            {
                var oops = decryptor.TransformFinalBlock(ciphertext, 0, ciphertext.Length);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("caught: " + e.Message);
        }
    
        // Last block of ciphertext is used as IV to encrypt a little bit more
        var lastBlock = new byte[16];
        var modifiedCiphertext = new byte[ciphertext.Length + 16];
    
        Array.Copy(ciphertext, ciphertext.Length - 16, lastBlock, 0, 16);
        aes.IV = lastBlock;
    
        using (var encryptor = aes.CreateEncryptor())
        {
            var dummy = Encoding.UTF8.GetBytes("$");
            var padded = encryptor.TransformFinalBlock(dummy, 0, dummy.Length);
    
            // Set modifiedCiphertext = ciphertext + padded
            Array.Copy(ciphertext, modifiedCiphertext, ciphertext.Length);
            Array.Copy(padded, 0, modifiedCiphertext, ciphertext.Length, padded.Length);
            Console.WriteLine("modified ciphertext: " + BitConverter.ToString(modifiedCiphertext));
        }
    
        // Put back the original IV, and now we can decrypt...
        aes.IV = originalIV;
    
        using (var decryptor = aes.CreateDecryptor())
        {
            var recovered = decryptor.TransformFinalBlock(modifiedCiphertext, 0, modifiedCiphertext.Length);
            var str = Encoding.UTF8.GetString(recovered);
            Console.WriteLine(str);
    
            // Now you can remove the '$' from the end
        }
    }
    

    你知道用来加密的算法吗?知道<代码>AES/CBC/NOP添加正常。你能得到想要的结果吗?@KarthikAMR我编辑了这篇文章。请根据您的描述检查错误与Base64解码有关,与解密无关。你试过追踪数据到解密吗?我在解密端换了。但是没有成功;请看我的编辑2:有问题。请看
    AESManaged
    的C#文档。padding属性有一个getter和setter<代码>填充模式。无似乎是您需要的。Windows phone不支持此模式。查看托管的.Padding属性文档中的平台列表。[]然后您需要1)在加密端进行更改,2)在解密端使用不同的平台,或3)从基础添加解码功能,构建您自己的AES/CBC/NOP。如果您有一个AES/ECB模式可以处理单个块,那么这并不太困难。谢谢您的建议。让我试试这些箱子。但我不能在加密端更改,因为文件已经加密。嗨,FOA,我不得不为回复太晚而道歉。同时,我正在检查不同的情况下,你的建议,因为它不适合我的cyperText。你可以在我的问题中查看我的cypertext,我给出了链接。它在解密后给出相同的文本。但是对于普通文本(您给出的示例),它工作得很好。这里有什么遗漏吗…?我不能检查你的密文是粘贴文本,没有密钥,iv和明文。加密一些明文,并给出原始明文、密钥、iv和密文,以及另一端的密文、密钥、iv和恢复的明文。任何简单的消息和随机密钥都可以用来比较结果。嗨..,这是我上传到OneDrive的纯文本文件和加密文件[]。我把我的IV&Key放在Key.txt文件中,该文件使用AES/CBC/NoPadding算法进行加密。如果您想查看文件,请尝试下载。我在txt文件中使用相同的IV和密钥进行加密和解密。如果你想知道更多
    var rfc2898 = new Rfc2898DeriveBytes("password", new byte[8]);
    
    using (var aes = new AesManaged())
    {
        aes.Key = rfc2898.GetBytes(32);
        aes.IV = rfc2898.GetBytes(16);
    
        var originalIV = aes.IV; // keep a copy
    
        // Prepare sample plaintext that has no padding
        aes.Padding = PaddingMode.None;
        var plaintext = Encoding.UTF8.GetBytes("this plaintext has 32 characters");
        byte[] ciphertext;
        using (var encryptor = aes.CreateEncryptor())
        {
            ciphertext = encryptor.TransformFinalBlock(plaintext, 0, plaintext.Length);
            Console.WriteLine("ciphertext: " + BitConverter.ToString(ciphertext));
        }
    
        // From this point on we do everything with PKCS#7 padding
        aes.Padding = PaddingMode.PKCS7;
    
        // This won't decrypt -- wrong padding
        try
        {
            using (var decryptor = aes.CreateDecryptor())
            {
                var oops = decryptor.TransformFinalBlock(ciphertext, 0, ciphertext.Length);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("caught: " + e.Message);
        }
    
        // Last block of ciphertext is used as IV to encrypt a little bit more
        var lastBlock = new byte[16];
        var modifiedCiphertext = new byte[ciphertext.Length + 16];
    
        Array.Copy(ciphertext, ciphertext.Length - 16, lastBlock, 0, 16);
        aes.IV = lastBlock;
    
        using (var encryptor = aes.CreateEncryptor())
        {
            var dummy = Encoding.UTF8.GetBytes("$");
            var padded = encryptor.TransformFinalBlock(dummy, 0, dummy.Length);
    
            // Set modifiedCiphertext = ciphertext + padded
            Array.Copy(ciphertext, modifiedCiphertext, ciphertext.Length);
            Array.Copy(padded, 0, modifiedCiphertext, ciphertext.Length, padded.Length);
            Console.WriteLine("modified ciphertext: " + BitConverter.ToString(modifiedCiphertext));
        }
    
        // Put back the original IV, and now we can decrypt...
        aes.IV = originalIV;
    
        using (var decryptor = aes.CreateDecryptor())
        {
            var recovered = decryptor.TransformFinalBlock(modifiedCiphertext, 0, modifiedCiphertext.Length);
            var str = Encoding.UTF8.GetString(recovered);
            Console.WriteLine(str);
    
            // Now you can remove the '$' from the end
        }
    }