加密的文件未正确解密

时间:2018-12-12 15:11:49

标签: c# encryption serialization

我遇到以下问题:有一个名为UserConfigStorage的类,其中有8个字符串。程序首次运行后,将要求用户输入其个人信息,并将这些信息存储在上述8个字符串中。用户单击按钮后,该类将被序列化和加密,以防止用户对其进行修改。然后,当程序第二次运行时,在Form_Load事件中,文件被解密,并且文件中的信息使用反序列化方法加载到文本框。但是,会抛出一个异常System.Runtime.Serialization.SerializationException: End of Stream encountered before parsing was completed,并且无法读取该文件。

查看代码和生成的文件时,我发现生成的解密文件没有全部信息。实际上,它只存储了8个字符串中的6个。

方法如下:

序列化方法

    public void SerializeUserConfig(string fileName)
    {
        try
        {
            FileStream fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            BinaryFormatter binForm = new BinaryFormatter();
            binForm.Serialize(fileStream, userconfigstorage);
            fileStream.Close();

            encryptor.Encrypt(fileName, perfilAcesso.GetUserConfigPath() + "Encrypted", "syndra15OP");

            File.Delete(fileName);

            MessageBox.Show("Dados salvos com sucesso!");
        }
        catch (Exception exception)
        {
            errorlog.SetError(exception.ToString());
            SerializeError(perfilAcesso.GetUserErrorLogPath());
            MessageBox.Show("Houve um erro ao salvar as configurações!\nPor favor, contate o desenvolvedor.\n\nEID: 002");
        }
    }

反序列化方法

    public UserConfigStorage DeserializeUserConfig(string fileName)
    {
        encryptor.Decrypt(perfilAcesso.GetUserConfigPath() + "Encrypted", fileName, "syndra15OP");

        FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
        BinaryFormatter binForm = new BinaryFormatter();
        UserConfigStorage userconfigstorage = (UserConfigStorage)binForm.Deserialize(fileStream);
        fileStream.Close();
        return userconfigstorage;
    }

加密方法(在Encryptor类中)

    public void Encrypt(string input, string output, string strHash)
    {
        FileStream inStream, outStream;
        CryptoStream cryStream;
        TripleDESCryptoServiceProvider tdc = new TripleDESCryptoServiceProvider();
        MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

        byte[] byteHash, byteText;

        inStream = new FileStream(input, FileMode.Open, FileAccess.Read);
        outStream = new FileStream(output, FileMode.OpenOrCreate, FileAccess.Write);

        byteHash = md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(strHash));
        byteText = File.ReadAllBytes(input);

        md5.Clear();

        tdc.Key = byteHash;
        tdc.Mode = CipherMode.ECB;

        cryStream = new CryptoStream(outStream, tdc.CreateEncryptor(), CryptoStreamMode.Write);

        int bytesRead;
        long length, position = 0;
        length = inStream.Length;

        while (position < length)
        {
            bytesRead = inStream.Read(byteText, 0, byteText.Length);
            position += bytesRead;

            cryStream.Write(byteText, 0, bytesRead);
        }

        inStream.Close();
        outStream.Close();
        cryStream.Close();
    }

解密方法

//The same as Encrypt(), except that for cryStream, it's tdc.CreateDecryptor()

要序列化的类

[Serializable()]
public class UserConfigStorage
{
    // 8 strings here, all public, each with its public getter
}

请问有人导致文件无法完全解密的原因是什么? 预先感谢!

1 个答案:

答案 0 :(得分:1)

是的,using绝对是您在这里的朋友! :)

为什么要将该对象序列化为文件,然后再将其加密为另一个文件?

我已经清理了一下您的代码,这应该可以正常工作:

public void SerializeUserConfig(string fileName)
{
    try
    {
        Encrypt(userconfigstorage, Path.Combine(perfilAcesso.GetUserConfigPath(), fileName), "syndra15OP");
        MessageBox.Show("Dados salvos com sucesso!");
    }
    catch (Exception exception)
    {
        errorlog.SetError(exception.ToString());
        SerializeError(perfilAcesso.GetUserErrorLogPath());
        MessageBox.Show("Houve um erro ao salvar as configurações!\nPor favor, contate o desenvolvedor.\n\nEID: 002");
    }
}

public UserConfigStorage DeserializeUserConfig(string fileName)
{
    return Decrypt(Path.Combine(perfilAcesso.GetUserConfigPath(), fileName), "syndra15OP");
}

public void Encrypt(UserConfigStorage input, string filePath, string strHash)
{
    using (TripleDESCryptoServiceProvider tdc = new TripleDESCryptoServiceProvider())
    {
        using (FileStream outStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write))
        {

            using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
            {
                tdc.Key = md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(strHash));
                md5.Clear();
            }

            tdc.Mode = CipherMode.ECB;

            using (CryptoStream cryStream = new CryptoStream(outStream, tdc.CreateEncryptor(), CryptoStreamMode.Write))
            {
                BinaryFormatter binForm = new BinaryFormatter();
                binForm.Serialize(cryStream, input);
            }
        }
    }
}

public UserConfigStorage Decrypt(string filePath, string strHash)
{
    UserConfigStorage output;

    using (TripleDESCryptoServiceProvider tdc = new TripleDESCryptoServiceProvider())
    {
        using (FileStream outStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {

            using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
            {
                tdc.Key = md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(strHash));
                md5.Clear();
            }

            tdc.Mode = CipherMode.ECB;

            using (CryptoStream cryStream = new CryptoStream(outStream, tdc.CreateDecryptor(), CryptoStreamMode.Read))
            {
                BinaryFormatter binForm = new BinaryFormatter();
                output = binForm.Deserialize(cryStream) as UserConfigStorage;
            }
        }
    }

    return output;
}

致谢