填充字符出现时的解密问题

时间:2017-11-05 11:00:16

标签: c# encryption aes

  

我在文本框中输入存档名称以获取此存档的消息。

     

我在文本框中写密码

     

我计算盐。

按钮单击

    private void button1_Click_1(object sender, EventArgs e)
    {
        String message;
        String password;
        String result;
        String resultSalt;
        String nameResult;
        byte[] salt;


        password = textBox2.Text;
        nameResult = textBox3.Text;
        new RNGCryptoServiceProvider().GetBytes(salt = new byte[16]);

        resultSalt = Convert.ToBase64String(salt);

        if (radioButton1.Checked == true)
        {
            message = readArchive();
            result = Encrypt(message,password,resultSalt);
            try
            {
                File.WriteAllText(nameResult, result);
                MessageBox.Show("Encrypt Ok");
            }
            catch
            {
                MessageBox.Show("Error");
            }

        }
        else
        {
            message = readArchive();
            result = Decrypt(message,password,result);
            try
            {
                File.WriteAllText(nameResult, resultSalt);
                MessageBox.Show("Decrypt OK");
            }
            catch
            {
                MessageBox.Show("Error");
            }

        }
    }

方法加密

    public static string Encrypt(string message, string pass, string salt)
    {
        AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
        DeriveBytes rgb = new Rfc2898DeriveBytes(pass, Encoding.Unicode.GetBytes(salt), 9);
        byte[] key = rgb.GetBytes(aes.KeySize >> 3);
        byte[] iv = rgb.GetBytes(aes.BlockSize >> 3);
        aes.Mode = CipherMode.CBC;
        aes.Key = key;
        aes.IV = iv;
        ICryptoTransform encryptor = aes.CreateEncryptor();
        byte[] data = Encoding.Unicode.GetBytes(message);
        byte[] dataencrypt = encryptor.TransformFinalBlock(data, 0, data.Length);
        return Convert.ToBase64String(dataencrypt);
    }

方法解密

    public static string Decrypt(string message, string pass, string salt)
    {
        AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
        DeriveBytes rgb = new Rfc2898DeriveBytes(pass, Encoding.Unicode.GetBytes(salt), 9);
        byte[] key = rgb.GetBytes(aes.KeySize >> 3);
        byte[] iv = rgb.GetBytes(aes.BlockSize >> 3);
        aes.Mode = CipherMode.CBC;
        aes.Key = key;
        aes.IV = iv;
        ICryptoTransform decryptor = aes.CreateDecryptor();
        byte[] data = Convert.FromBase64String(message);
        byte[] datadecrypt = decryptor.TransformFinalBlock(data, 0, data.Length);
        return Encoding.Unicode.GetString(datadecrypt);
    }

方法readArchive

    private string readArchive()
    {
        String nameArchive = textBox1.Text;
        String text = "";
        try
        {

            text = File.ReadAllText(@nameArchive);

        }
        catch
        {

            MessageBox.Show("Error.");
        }
        return text;
    }

错误行

byte[] datadecrypt = decryptor.TransformFinalBlock(data, 0, data.Length);
  

类型' System.Security.Cryptography.CryptographicException'未处理的例外情况。在System.Core.dll

中      

附加信息:字符之间的填充无效,无法删除。

1 个答案:

答案 0 :(得分:2)

使用resultSalt = Convert.ToBase64String(salt)对您的salt进行base64编码,然后再将其传递给Encrypt(..),然后使用Encoding.Unicode.GetBytes(salt)获取base64编码字符串的字节值。这可能不是您想要的,而是将其作为byte []传递,或者在使用之前进行正确的base64解码。

但这不是主要问题..主要问题是您将result传递给Decrypt(..)而不是resultSalt。但是当你这样做时,你需要确保它与Encrypt(..)上使用的相同。目前你在每次点击时都会产生新的盐。